├── .auto-changelog ├── .dockerignore ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── mergify.yml └── workflows │ ├── cd_docker.yml │ ├── ci.yml │ ├── ci_codeql.yml │ ├── codesee-arch-diagram.yml │ └── stale.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── benchmark ├── README.md ├── postEvaluation.json ├── postEvaluation.output ├── postEvaluation.target └── torch.png ├── browser └── flagr-ui │ ├── .env │ ├── .env.production │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.png │ └── index.html │ ├── src │ ├── App.vue │ ├── components │ │ ├── DebugConsole.vue │ │ ├── Flag.vue │ │ ├── FlagHistory.vue │ │ ├── Flags.vue │ │ ├── MarkdownEditor.vue │ │ └── Spinner.vue │ ├── constants.js │ ├── helpers │ │ └── helpers.js │ ├── main.js │ ├── operators.json │ └── router │ │ └── index.js │ └── vue.config.js ├── buildscripts └── demo_sqlite3.db ├── codecov.yml ├── docker-compose.kafka.yml ├── docs ├── .nojekyll ├── _coverpage.md ├── _sidebar.md ├── api_docs │ ├── bundle.yaml │ └── index.html ├── flagr_debugging.md ├── flagr_env.md ├── flagr_overview.md ├── flagr_use_cases.md ├── home.md ├── images │ ├── demo_debugging_console.png │ ├── demo_dynamic_configuration.png │ ├── demo_exp1.png │ ├── demo_exp2.png │ ├── demo_ff.png │ ├── demo_homepage.png │ ├── demo_readme.png │ ├── favicon.png │ ├── flagr_arch.png │ ├── flagr_running_example_1.png │ ├── flagr_running_example_2.png │ ├── flagr_running_example_3.png │ ├── flagr_running_example_4.png │ ├── flagr_running_example_5.png │ ├── flagr_running_example_6.png │ ├── flagr_running_example_7.png │ └── logo.png └── index.html ├── go.mod ├── go.sum ├── integration_tests ├── Dockerfile-Integration-Test ├── Makefile ├── docker-compose.yml └── test.sh ├── pkg ├── config │ ├── config.go │ ├── config_test.go │ ├── env.go │ ├── middleware.go │ └── middleware_test.go ├── entity │ ├── constraint.go │ ├── constraint_test.go │ ├── db.go │ ├── db_test.go │ ├── distribution.go │ ├── distribution_test.go │ ├── evaluator.go │ ├── fixture.go │ ├── flag.go │ ├── flag_entity_type.go │ ├── flag_snapshot.go │ ├── flag_snapshot_test.go │ ├── flag_test.go │ ├── logger.go │ ├── segment.go │ ├── segment_test.go │ ├── tag.go │ ├── user.go │ ├── variant.go │ └── variant_test.go ├── handler │ ├── crud.go │ ├── crud_flag_creation.go │ ├── crud_flag_creation_test.go │ ├── crud_test.go │ ├── data_record_frame.go │ ├── data_record_frame_test.go │ ├── data_recorder.go │ ├── data_recorder_kafka.go │ ├── data_recorder_kafka_test.go │ ├── data_recorder_kinesis.go │ ├── data_recorder_kinesis_test.go │ ├── data_recorder_pubsub.go │ ├── data_recorder_pubsub_test.go │ ├── data_recorder_test.go │ ├── error.go │ ├── error_test.go │ ├── eval.go │ ├── eval_cache.go │ ├── eval_cache_fetcher.go │ ├── eval_cache_fetcher_test.go │ ├── eval_cache_test.go │ ├── eval_test.go │ ├── export.go │ ├── export_test.go │ ├── fixture.go │ ├── handler.go │ ├── handler_test.go │ ├── subject.go │ ├── subject_test.go │ ├── testdata │ │ ├── certificates │ │ │ ├── alice.crt │ │ │ ├── alice.key │ │ │ ├── bob.crt │ │ │ ├── bob.key │ │ │ ├── ca.crt │ │ │ ├── carol.crt │ │ │ └── carol.key │ │ └── sample_eval_cache.json │ ├── validate.go │ └── validate_test.go ├── mapper │ └── entity_restapi │ │ ├── e2r │ │ └── e2r.go │ │ └── r2e │ │ └── r2e.go └── util │ ├── util.go │ └── util_test.go ├── swagger ├── evaluation.yaml ├── evaluation_batch.yaml ├── export_eval_cache_json.yaml ├── export_sqlite.yaml ├── flag.yaml ├── flag_enabled.yaml ├── flag_entity_types.yaml ├── flag_restore.yaml ├── flag_segment.yaml ├── flag_segment_constraint.yaml ├── flag_segment_constraints.yaml ├── flag_segment_distributions.yaml ├── flag_segments.yaml ├── flag_segments_reorder.yaml ├── flag_snapshots.yaml ├── flag_tag.yaml ├── flag_tags.yaml ├── flag_variant.yaml ├── flag_variants.yaml ├── flags.yaml ├── health.yaml ├── index.yaml └── tags.yaml └── swagger_gen ├── cmd └── flagr-server │ └── main.go ├── models ├── constraint.go ├── create_constraint_request.go ├── create_flag_request.go ├── create_segment_request.go ├── create_tag_request.go ├── create_variant_request.go ├── distribution.go ├── error.go ├── eval_context.go ├── eval_debug_log.go ├── eval_result.go ├── evaluation_batch_request.go ├── evaluation_batch_response.go ├── evaluation_entity.go ├── flag.go ├── flag_snapshot.go ├── health.go ├── put_distributions_request.go ├── put_flag_request.go ├── put_segment_reorder_request.go ├── put_segment_request.go ├── put_variant_request.go ├── segment.go ├── segment_debug_log.go ├── set_flag_enabled_request.go ├── tag.go └── variant.go └── restapi ├── configure_flagr.go ├── doc.go ├── embedded_spec.go ├── operations ├── constraint │ ├── create_constraint.go │ ├── create_constraint_parameters.go │ ├── create_constraint_responses.go │ ├── create_constraint_urlbuilder.go │ ├── delete_constraint.go │ ├── delete_constraint_parameters.go │ ├── delete_constraint_responses.go │ ├── delete_constraint_urlbuilder.go │ ├── find_constraints.go │ ├── find_constraints_parameters.go │ ├── find_constraints_responses.go │ ├── find_constraints_urlbuilder.go │ ├── put_constraint.go │ ├── put_constraint_parameters.go │ ├── put_constraint_responses.go │ └── put_constraint_urlbuilder.go ├── distribution │ ├── find_distributions.go │ ├── find_distributions_parameters.go │ ├── find_distributions_responses.go │ ├── find_distributions_urlbuilder.go │ ├── put_distributions.go │ ├── put_distributions_parameters.go │ ├── put_distributions_responses.go │ └── put_distributions_urlbuilder.go ├── evaluation │ ├── post_evaluation.go │ ├── post_evaluation_batch.go │ ├── post_evaluation_batch_parameters.go │ ├── post_evaluation_batch_responses.go │ ├── post_evaluation_batch_urlbuilder.go │ ├── post_evaluation_parameters.go │ ├── post_evaluation_responses.go │ └── post_evaluation_urlbuilder.go ├── export │ ├── get_export_eval_cache_json.go │ ├── get_export_eval_cache_json_parameters.go │ ├── get_export_eval_cache_json_responses.go │ ├── get_export_eval_cache_json_urlbuilder.go │ ├── get_export_sqlite.go │ ├── get_export_sqlite_parameters.go │ ├── get_export_sqlite_responses.go │ └── get_export_sqlite_urlbuilder.go ├── flag │ ├── create_flag.go │ ├── create_flag_parameters.go │ ├── create_flag_responses.go │ ├── create_flag_urlbuilder.go │ ├── delete_flag.go │ ├── delete_flag_parameters.go │ ├── delete_flag_responses.go │ ├── delete_flag_urlbuilder.go │ ├── find_flags.go │ ├── find_flags_parameters.go │ ├── find_flags_responses.go │ ├── find_flags_urlbuilder.go │ ├── get_flag.go │ ├── get_flag_entity_types.go │ ├── get_flag_entity_types_parameters.go │ ├── get_flag_entity_types_responses.go │ ├── get_flag_entity_types_urlbuilder.go │ ├── get_flag_parameters.go │ ├── get_flag_responses.go │ ├── get_flag_snapshots.go │ ├── get_flag_snapshots_parameters.go │ ├── get_flag_snapshots_responses.go │ ├── get_flag_snapshots_urlbuilder.go │ ├── get_flag_urlbuilder.go │ ├── put_flag.go │ ├── put_flag_parameters.go │ ├── put_flag_responses.go │ ├── put_flag_urlbuilder.go │ ├── restore_flag.go │ ├── restore_flag_parameters.go │ ├── restore_flag_responses.go │ ├── restore_flag_urlbuilder.go │ ├── set_flag_enabled.go │ ├── set_flag_enabled_parameters.go │ ├── set_flag_enabled_responses.go │ └── set_flag_enabled_urlbuilder.go ├── flagr_api.go ├── health │ ├── get_health.go │ ├── get_health_parameters.go │ ├── get_health_responses.go │ └── get_health_urlbuilder.go ├── segment │ ├── create_segment.go │ ├── create_segment_parameters.go │ ├── create_segment_responses.go │ ├── create_segment_urlbuilder.go │ ├── delete_segment.go │ ├── delete_segment_parameters.go │ ├── delete_segment_responses.go │ ├── delete_segment_urlbuilder.go │ ├── find_segments.go │ ├── find_segments_parameters.go │ ├── find_segments_responses.go │ ├── find_segments_urlbuilder.go │ ├── put_segment.go │ ├── put_segment_parameters.go │ ├── put_segment_responses.go │ ├── put_segment_urlbuilder.go │ ├── put_segments_reorder.go │ ├── put_segments_reorder_parameters.go │ ├── put_segments_reorder_responses.go │ └── put_segments_reorder_urlbuilder.go ├── tag │ ├── create_tag.go │ ├── create_tag_parameters.go │ ├── create_tag_responses.go │ ├── create_tag_urlbuilder.go │ ├── delete_tag.go │ ├── delete_tag_parameters.go │ ├── delete_tag_responses.go │ ├── delete_tag_urlbuilder.go │ ├── find_all_tags.go │ ├── find_all_tags_parameters.go │ ├── find_all_tags_responses.go │ ├── find_all_tags_urlbuilder.go │ ├── find_tags.go │ ├── find_tags_parameters.go │ ├── find_tags_responses.go │ └── find_tags_urlbuilder.go └── variant │ ├── create_variant.go │ ├── create_variant_parameters.go │ ├── create_variant_responses.go │ ├── create_variant_urlbuilder.go │ ├── delete_variant.go │ ├── delete_variant_parameters.go │ ├── delete_variant_responses.go │ ├── delete_variant_urlbuilder.go │ ├── find_variants.go │ ├── find_variants_parameters.go │ ├── find_variants_responses.go │ ├── find_variants_urlbuilder.go │ ├── put_variant.go │ ├── put_variant_parameters.go │ ├── put_variant_responses.go │ └── put_variant_urlbuilder.go └── server.go /.auto-changelog: -------------------------------------------------------------------------------- 1 | { 2 | "template": "keepachangelog", 3 | "unreleased": true, 4 | "startingDate": "2021-08-08", 5 | "tagPattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" 6 | } 7 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/*.swp 2 | cover.out 3 | *~ 4 | flagr 5 | !*/ 6 | site/ 7 | **/*.test 8 | **/*.sublime-workspace 9 | /.idea/ 10 | **/access.log 11 | vendor/**/*.js 12 | vendor/**/*.json 13 | release 14 | .DS_Store 15 | *.syso 16 | coverage.txt 17 | .vscode/ 18 | .snap 19 | *.tar.bz2 20 | parts/ 21 | prime/ 22 | snap/.snapcraft/ 23 | stage/ 24 | _data/ 25 | .env.local 26 | flagr.sqlite 27 | ./browser/flagr-ui/node_modules 28 | Dockerfile 29 | integration_tests/ 30 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # All files use LF as eol 2 | * text=auto eol=lf 3 | 4 | # Remove vendor folder from the diff 5 | vendor/**/* -diff -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Expected Behavior 4 | 5 | 6 | 7 | ## Current Behavior 8 | 9 | 10 | 11 | ## Possible Solution 12 | 13 | 14 | 15 | ## Steps to Reproduce (for bugs) 16 | 17 | 18 | 1. 19 | 2. 20 | 3. 21 | 4. 22 | 23 | ## Context 24 | 25 | 26 | 27 | ## Your Environment 28 | 29 | * Version used (`flagr version`): 30 | * Server type and version: 31 | * Operating System and version (`uname -a`): 32 | * Link to your project: 33 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Motivation and Context 7 | 8 | 9 | 10 | ## How Has This Been Tested? 11 | 12 | 13 | 14 | 15 | ## Types of changes 16 | 17 | - [ ] Bug fix (non-breaking change which fixes an issue) 18 | - [ ] New feature (non-breaking change which adds functionality) 19 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 20 | 21 | ## Checklist: 22 | 23 | 24 | - [ ] My code follows the code style of this project. 25 | - [ ] My change requires a change to the documentation. 26 | - [ ] I have updated the documentation accordingly. 27 | - [ ] I have added tests to cover my changes. 28 | - [ ] All new and existing tests passed. -------------------------------------------------------------------------------- /.github/mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: Automatic merge on approval 3 | conditions: 4 | - "#approved-reviews-by>=2" 5 | - check-success=ui_lint 6 | - check-success=unit_test 7 | - check-success=integration_test 8 | - base=main 9 | - label!=wip 10 | - -title~=(?i)wip 11 | actions: 12 | merge: 13 | method: merge 14 | -------------------------------------------------------------------------------- /.github/workflows/cd_docker.yml: -------------------------------------------------------------------------------- 1 | name: cd_docker 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> "$GITHUB_ENV" 13 | - name: Set up QEMU 14 | uses: docker/setup-qemu-action@v3 15 | - name: Set up Docker Buildx 16 | uses: docker/setup-buildx-action@v3 17 | - name: Publish Docker SemVer Tag 18 | uses: elgohr/Publish-Docker-Github-Action@v5 19 | with: 20 | name: openflagr/flagr 21 | username: ${{ github.actor }} 22 | password: ${{ secrets.GITHUB_TOKEN }} 23 | registry: ghcr.io 24 | platforms: linux/amd64,linux/arm64 25 | tags: "latest,${{ env.RELEASE_VERSION }}" 26 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | pull_request: 7 | 8 | jobs: 9 | unit_test: 10 | runs-on: ubuntu-latest 11 | env: 12 | CGO_ENABLED: 0 13 | steps: 14 | - name: Set up Go 15 | uses: actions/setup-go@v5 16 | with: 17 | go-version: 1.24 18 | - name: Check out source code 19 | uses: actions/checkout@v4 20 | - run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" 21 | - run: make deps 22 | - run: make verify_swagger_nochange 23 | - run: make ci 24 | - run: make benchmark 25 | - uses: codecov/codecov-action@v4 26 | ui_lint: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/setup-node@v4 30 | with: 31 | node-version: '16' 32 | - name: Check out source code 33 | uses: actions/checkout@v4 34 | - run: cd browser/flagr-ui && npm install 35 | - run: cd browser/flagr-ui && npm run lint 36 | integration_test: 37 | runs-on: ubuntu-latest 38 | steps: 39 | - name: Check out source code 40 | uses: actions/checkout@v4 41 | - run: cd integration_tests && make build-image 42 | - run: cd integration_tests && make down 43 | - run: cd integration_tests && make up 44 | - run: cd integration_tests && make test 45 | actionlint: 46 | runs-on: ubuntu-latest 47 | steps: 48 | - uses: actions/checkout@v4 49 | - name: Download actionlint 50 | id: get_actionlint 51 | run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 52 | shell: bash 53 | - name: Check workflow files 54 | run: ${{ steps.get_actionlint.outputs.executable }} -color 55 | shell: bash 56 | -------------------------------------------------------------------------------- /.github/workflows/codesee-arch-diagram.yml: -------------------------------------------------------------------------------- 1 | # This workflow was added by CodeSee. Learn more at https://codesee.io/ 2 | # This is v2.0 of this workflow file 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request_target: 8 | types: [opened, synchronize, reopened] 9 | 10 | name: CodeSee 11 | 12 | permissions: read-all 13 | 14 | jobs: 15 | codesee: 16 | runs-on: ubuntu-latest 17 | continue-on-error: true 18 | name: Analyze the repo with CodeSee 19 | steps: 20 | - uses: Codesee-io/codesee-action@v2 21 | with: 22 | codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} 23 | codesee-url: https://app.codesee.io 24 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: '17 21 * * *' 6 | 7 | jobs: 8 | stale: 9 | 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | 15 | steps: 16 | - uses: actions/stale@v9 17 | with: 18 | repo-token: ${{ secrets.GITHUB_TOKEN }} 19 | stale-issue-message: 'Stale issue message' 20 | stale-pr-message: 'Stale pull request message' 21 | stale-issue-label: 'no-issue-activity' 22 | stale-pr-label: 'no-pr-activity' 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.swp 2 | *.out 3 | *~ 4 | flagr 5 | flagr.sqlite 6 | !*/ 7 | site/ 8 | **/*.test 9 | **/*.sublime-workspace 10 | /.idea/ 11 | **/access.log 12 | vendor/**/*.js 13 | vendor/**/*.json 14 | release 15 | .DS_Store 16 | *.syso 17 | coverage.txt 18 | .vscode/ 19 | .snap 20 | *.tar.bz2 21 | parts/ 22 | prime/ 23 | snap/.snapcraft/ 24 | stage/ 25 | .env.local 26 | _tools/ 27 | _data 28 | coverage.txt 29 | /vendor 30 | .history 31 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | https://github.com/openflagr/flagr/releases 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ###################################### 2 | # Prepare npm_builder 3 | ###################################### 4 | FROM node:16 as npm_builder 5 | WORKDIR /go/src/github.com/openflagr/flagr 6 | ADD . . 7 | ARG FLAGR_UI_POSSIBLE_ENTITY_TYPES=null 8 | ENV VUE_APP_FLAGR_UI_POSSIBLE_ENTITY_TYPES ${FLAGR_UI_POSSIBLE_ENTITY_TYPES} 9 | RUN make build_ui 10 | 11 | ###################################### 12 | # Prepare go_builder 13 | ###################################### 14 | FROM golang:1.24-alpine as go_builder 15 | WORKDIR /go/src/github.com/openflagr/flagr 16 | 17 | RUN apk add --no-cache git make build-base 18 | ADD . . 19 | ENV CGO_ENABLED=0 20 | RUN make build 21 | 22 | FROM alpine 23 | 24 | COPY --from=go_builder /go/src/github.com/openflagr/flagr/flagr . 25 | 26 | ENV HOST=0.0.0.0 27 | ENV PORT=18000 28 | ENV FLAGR_DB_DBDRIVER=sqlite3 29 | ENV FLAGR_DB_DBCONNECTIONSTR=/data/demo_sqlite3.db 30 | ENV FLAGR_RECORDER_ENABLED=false 31 | 32 | COPY --from=npm_builder /go/src/github.com/openflagr/flagr/browser/flagr-ui/dist ./browser/flagr-ui/dist 33 | 34 | RUN addgroup -S appgroup && adduser -S appuser -G appgroup 35 | USER appuser 36 | 37 | ADD --chown=appuser:appgroup ./buildscripts/demo_sqlite3.db /data/demo_sqlite3.db 38 | 39 | EXPOSE 18000 40 | 41 | CMD "./flagr" 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PWD := $(shell pwd) 2 | GOPATH := $(shell go env GOPATH) 3 | UIPATH := $(PWD)/browser/flagr-ui 4 | 5 | ################################ 6 | ### Public 7 | ################################ 8 | 9 | all: deps gen build build_ui run 10 | 11 | rebuild: gen build 12 | 13 | test: verifiers 14 | @go test -covermode=atomic -coverprofile=coverage.txt github.com/openflagr/flagr/pkg/... 15 | 16 | .PHONY: benchmark 17 | benchmark: 18 | @go test -benchmem -run=^$$ -bench . ./pkg/... 19 | 20 | ci: test 21 | 22 | .PHONY: vendor 23 | vendor: 24 | @go mod tidy 25 | @go mod vendor 26 | 27 | build: 28 | @echo "Building Flagr Server to $(PWD)/flagr ..." 29 | @CGO_ENABLED=0 go build -o $(PWD)/flagr github.com/openflagr/flagr/swagger_gen/cmd/flagr-server 30 | 31 | build_ui: 32 | @echo "Building Flagr UI ..." 33 | @cd ./browser/flagr-ui/; npm install && npm run build 34 | 35 | run_ui: 36 | @cd ./browser/flagr-ui/; npm run serve 37 | 38 | run: 39 | @$(PWD)/flagr --port 18000 40 | 41 | start: 42 | $(MAKE) -j run run_ui 43 | 44 | gen: api_docs swagger 45 | 46 | deps: 47 | @CGO_ENABLED=0 go install github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 48 | @CGO_ENABLED=0 go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 49 | 50 | serve_docs: 51 | @npm install -g docsify-cli@4 52 | @docsify serve $(PWD)/docs 53 | 54 | ################################ 55 | ### Private 56 | ################################ 57 | 58 | api_docs: 59 | @echo "Installing swagger-merger" && npm install swagger-merger -g 60 | @swagger-merger -i $(PWD)/swagger/index.yaml -o $(PWD)/docs/api_docs/bundle.yaml 61 | 62 | verifiers: verify_lint verify_swagger 63 | 64 | verify_lint: 65 | @echo "Running $@" 66 | @golangci-lint run --timeout 5m -D errcheck ./pkg/... 67 | 68 | verify_swagger: 69 | @echo "Running $@" 70 | @swagger validate $(PWD)/docs/api_docs/bundle.yaml 71 | 72 | verify_swagger_nochange: swagger 73 | @echo "Running verify_swagger_nochange to make sure the swagger generated code is checked in" 74 | @git diff --exit-code 75 | 76 | clean: 77 | @echo "Cleaning up all the generated files" 78 | @find . -name '*.test' | xargs rm -fv 79 | @rm -rf build 80 | @rm -rf release 81 | 82 | swagger: verify_swagger 83 | @echo "Regenerate swagger files" 84 | @rm -f /tmp/configure_flagr.go 85 | @cp $(PWD)/swagger_gen/restapi/configure_flagr.go /tmp/configure_flagr.go 2>/dev/null || : 86 | @rm -rf $(PWD)/swagger_gen 87 | @mkdir $(PWD)/swagger_gen 88 | @swagger generate server -t ./swagger_gen -f $(PWD)/docs/api_docs/bundle.yaml 89 | @cp /tmp/configure_flagr.go $(PWD)/swagger_gen/restapi/configure_flagr.go 2>/dev/null || : 90 | -------------------------------------------------------------------------------- /benchmark/README.md: -------------------------------------------------------------------------------- 1 | ## Benchmark with vegeta 2 | 3 | ``` 4 | go get -u github.com/tsenart/vegeta 5 | vegeta attack -targets ./postEvaluation.target -body ./postEvaluation.json -output ./postEvaluation.output -workers 100 -rate 2000 6 | ``` 7 | 8 | ``` 9 | Requests [total, rate] 56521, 2000.04 10 | Duration [total, attack, wait] 28.2603654s, 28.259999871s, 365.529µs 11 | Latencies [mean, 50, 95, 99, max] 371.632µs, 327.991µs, 614.918µs, 1.385568ms, 12.50012ms 12 | Bytes In [total, mean] 23250552, 411.36 13 | Bytes Out [total, mean] 8308587, 147.00 14 | Success [ratio] 100.00% 15 | Status Codes [code:count] 200:56521 16 | Error Set: 17 | ``` 18 | 19 | ## Getting the flamegraph from go tool 20 | 21 | ``` 22 | curl http://localhost:18000/debug/pprof/profile -o /tmp/flagr_profile 23 | go tool pprof -http=":8081" /tmp/flagr_profile 24 | ``` 25 | 26 | ![torch.png](./torch.png) 27 | -------------------------------------------------------------------------------- /benchmark/postEvaluation.json: -------------------------------------------------------------------------------- 1 | { 2 | "entityID": "123", 3 | "entityType": "report", 4 | "entityContext": { 5 | "state": "CA" 6 | }, 7 | "flagID": 1 8 | } 9 | -------------------------------------------------------------------------------- /benchmark/postEvaluation.output: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/benchmark/postEvaluation.output -------------------------------------------------------------------------------- /benchmark/postEvaluation.target: -------------------------------------------------------------------------------- 1 | POST http://localhost:18000/api/v1/evaluation 2 | Content-Type: application/json 3 | -------------------------------------------------------------------------------- /benchmark/torch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/benchmark/torch.png -------------------------------------------------------------------------------- /browser/flagr-ui/.env: -------------------------------------------------------------------------------- 1 | BASE_URL="" 2 | VUE_APP_API_URL=http://127.0.0.1:18000/api/v1 3 | VUE_APP_FLAGR_UI_POSSIBLE_ENTITY_TYPES=null 4 | -------------------------------------------------------------------------------- /browser/flagr-ui/.env.production: -------------------------------------------------------------------------------- 1 | VUE_APP_API_URL=api/v1 2 | -------------------------------------------------------------------------------- /browser/flagr-ui/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /browser/flagr-ui/README.md: -------------------------------------------------------------------------------- 1 | # flagr-ui 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Run your tests 19 | ``` 20 | npm run test 21 | ``` 22 | 23 | ### Lints and fixes files 24 | ``` 25 | npm run lint 26 | ``` 27 | 28 | ### Upgrade vue-cli 29 | ``` 30 | npm install -g @vue/cli 31 | vue --version 32 | vue upgrade 33 | ``` 34 | 35 | ### Customize configuration 36 | See [Configuration Reference](https://cli.vuejs.org/config/). 37 | -------------------------------------------------------------------------------- /browser/flagr-ui/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /browser/flagr-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flagr-ui", 3 | "version": "1.1.18", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "watch": "vue-cli-service build --watch" 10 | }, 11 | "dependencies": { 12 | "@iktakahiro/markdown-it-katex": "^4.0.0", 13 | "axios": "^1.8.2", 14 | "core-js": "^3.4.4", 15 | "diff": "^3.4.0", 16 | "element-ui": "^2.4.6", 17 | "lodash.clone": "^4.5.0", 18 | "markdown-it": "^12.3.2", 19 | "vue": "^2.6.10", 20 | "vue-json-editor": "^1.2.0", 21 | "vue-router": "^2.7.0", 22 | "vuedraggable": "^2.14.1", 23 | "vuex": "^2.4.1", 24 | "xss": "^1.0.9" 25 | }, 26 | "devDependencies": { 27 | "@vue/cli-plugin-babel": "^5.0.8", 28 | "@vue/cli-plugin-eslint": "^5.0.8", 29 | "@vue/cli-service": "^5.0.8", 30 | "babel-eslint": "^10.0.3", 31 | "eslint": "^7.32.0", 32 | "eslint-plugin-vue": "^7.20.0", 33 | "less": "^3.11.3", 34 | "less-loader": "^8.1.1", 35 | "lodash": "^4.17.19", 36 | "minimist": ">=1.2.2", 37 | "vue-template-compiler": "^2.6.10" 38 | }, 39 | "eslintConfig": { 40 | "root": true, 41 | "env": { 42 | "node": true 43 | }, 44 | "extends": [ 45 | "plugin:vue/essential", 46 | "eslint:recommended" 47 | ], 48 | "rules": {}, 49 | "parserOptions": { 50 | "parser": "babel-eslint" 51 | } 52 | }, 53 | "postcss": { 54 | "plugins": { 55 | "autoprefixer": {} 56 | } 57 | }, 58 | "browserslist": [ 59 | "> 1%", 60 | "last 2 versions" 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /browser/flagr-ui/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/browser/flagr-ui/public/favicon.png -------------------------------------------------------------------------------- /browser/flagr-ui/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Flagr 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/components/MarkdownEditor.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 65 | 66 | 72 | 73 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/components/Spinner.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 49 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/constants.js: -------------------------------------------------------------------------------- 1 | const API_URL = process.env.VUE_APP_API_URL 2 | const FLAGR_UI_POSSIBLE_ENTITY_TYPES = process.env.VUE_APP_FLAGR_UI_POSSIBLE_ENTITY_TYPES 3 | 4 | export default { 5 | API_URL, 6 | FLAGR_UI_POSSIBLE_ENTITY_TYPES 7 | } 8 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/helpers/helpers.js: -------------------------------------------------------------------------------- 1 | function indexBy (arr, prop) { 2 | return arr.reduce((acc, el) => { 3 | acc[el[prop]] = el 4 | return acc 5 | }, {}) 6 | } 7 | 8 | function pluck (arr, prop) { 9 | return arr.map(el => el[prop]) 10 | } 11 | 12 | function sum (arr) { 13 | return arr.reduce((acc, el) => { 14 | acc += el 15 | return acc 16 | }, 0) 17 | } 18 | 19 | function get (obj, path, def) { 20 | const fullPath = path 21 | .replace(/\[/g, '.') 22 | .replace(/]/g, '') 23 | .split('.') 24 | .filter(Boolean) 25 | 26 | return fullPath.every(everyFunc) ? obj : def 27 | 28 | function everyFunc (step) { 29 | return !(step && (obj = obj[step]) === undefined) 30 | } 31 | } 32 | 33 | function handleErr (err) { 34 | let msg = get(err, 'response.data.message', 'request error') 35 | this.$message.error(msg) 36 | if (get(err, 'response.status') === 401) { 37 | let redirectURL = err.response.headers['www-authenticate'].split(`"`)[1] 38 | window.location = redirectURL 39 | return 40 | } 41 | } 42 | 43 | export default { 44 | indexBy, 45 | pluck, 46 | sum, 47 | get, 48 | handleErr 49 | } 50 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | 5 | import ElementUI from 'element-ui' 6 | import locale from 'element-ui/lib/locale/lang/en' 7 | import 'element-ui/lib/theme-chalk/index.css' 8 | 9 | import App from './App.vue' 10 | import router from './router' 11 | 12 | Vue.config.productionTip = false 13 | Vue.use(ElementUI, { locale }) 14 | 15 | // Autofocus certain fields 16 | Vue.directive('focus', { 17 | inserted: function (el) { 18 | el.__vue__.focus() 19 | } 20 | }) 21 | 22 | /* eslint-disable no-new */ 23 | 24 | new Vue({ 25 | render: h => h(App), 26 | router 27 | }).$mount('#app') 28 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/operators.json: -------------------------------------------------------------------------------- 1 | { 2 | "operators":[ 3 | {"value": "EQ", "label": "=="}, 4 | {"value": "NEQ", "label": "!="}, 5 | {"value": "LT", "label": "<"}, 6 | {"value": "LTE", "label": "<="}, 7 | {"value": "GT", "label": ">"}, 8 | {"value": "GTE", "label": ">="}, 9 | {"value": "EREG", "label": "=~"}, 10 | {"value": "NEREG", "label": "!~"}, 11 | {"value": "IN", "label": "IN"}, 12 | {"value": "NOTIN", "label": "NOT IN"}, 13 | {"value": "CONTAINS", "label": "CONTAINS"}, 14 | {"value": "NOTCONTAINS", "label": "NOT CONTAINS"} 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /browser/flagr-ui/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Flags from '@/components/Flags' 4 | import Flag from '@/components/Flag' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | mode: 'hash', 10 | routes: [ 11 | { 12 | path: '/', 13 | name: 'home', 14 | component: Flags 15 | }, 16 | { 17 | path: '/flags/:flagId', 18 | name: 'flag', 19 | component: Flag 20 | } 21 | ] 22 | }) 23 | -------------------------------------------------------------------------------- /browser/flagr-ui/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assetsDir: 'static', 3 | publicPath: process.env.BASE_URL 4 | } 5 | -------------------------------------------------------------------------------- /buildscripts/demo_sqlite3.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/buildscripts/demo_sqlite3.db -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | ignore: 3 | - "pkg/entity/autogenerated_*.go" 4 | range: 50..78 5 | -------------------------------------------------------------------------------- /docker-compose.kafka.yml: -------------------------------------------------------------------------------- 1 | mysql: 2 | image: mysql:5.6 3 | container_name: flagr-mysql 4 | environment: 5 | - MYSQL_ALLOW_EMPTY_PASSWORD=yes 6 | - MYSQL_DATABASE=flagr 7 | - MYSQL_USER=root 8 | ports: 9 | - "18100:3306" 10 | 11 | mysql8: 12 | image: mysql:8 13 | container_name: flagr-mysql 14 | environment: 15 | - MYSQL_ALLOW_EMPTY_PASSWORD=yes 16 | - MYSQL_DATABASE=flagr 17 | - MYSQL_USER=root 18 | ports: 19 | - "18101:3306" 20 | 21 | postgres: 22 | image: postgres:13 23 | container_name: flagr-postgres 24 | environment: 25 | POSTGRES_PASSWORD: "test" 26 | POSTGRES_USER: "test" 27 | POSTGRES_DB: "flagr" 28 | ports: 29 | - "18102:5432" 30 | 31 | zookeeper: 32 | image: confluentinc/cp-zookeeper 33 | container_name: flagr-zookeeper 34 | environment: 35 | ZOOKEEPER_CLIENT_PORT: 2181 36 | ZOOKEEPER_TICK_TIME: 2000 37 | ports: 38 | - "2181:2181" 39 | extra_hosts: 40 | - "moby:127.0.0.1" 41 | 42 | kafka: 43 | image: confluentinc/cp-kafka 44 | container_name: flagr-kafka 45 | links: 46 | - zookeeper 47 | environment: 48 | KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" 49 | KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9092" 50 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 51 | KAFKA_BROKER_ID: 1 52 | ports: 53 | - "9092:9092" 54 | extra_hosts: 55 | - "moby:127.0.0.1" 56 | 57 | kafka-manager: 58 | image: sheepkiller/kafka-manager 59 | container_name: flagr-kafka-manager 60 | ports: 61 | - "9000:9000" 62 | links: 63 | - zookeeper 64 | - kafka 65 | environment: 66 | ZK_HOSTS: "zookeeper:2181" 67 | extra_hosts: 68 | - "moby:127.0.0.1" 69 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/.nojekyll -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 |

Flagr

2 | 3 |

4 | Open source feature flagging, A/B testing,
5 | and dynamic configuration microservice in Go. 6 |
7 |
8 |

9 | 10 | [GitHub](https://github.com/openflagr/flagr) 11 | [Get Started](home) 12 | 13 | ![color](#74e5e0) 14 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - What's Flagr 2 | - [Get started](home.md) 3 | - [API 🔗](https://openflagr.github.io/flagr/api_docs) 4 | - Introduction 5 | - [Overview](flagr_overview.md) 6 | - [Use Cases](flagr_use_cases.md) 7 | - [Debug Console](flagr_debugging.md) 8 | - Server Configuration 9 | - [Env](flagr_env.md) 10 | - Client SDKs 11 | - [Ruby SDK 🔗](https://github.com/openflagr/rbflagr) 12 | - [Go SDK 🔗](https://github.com/openflagr/goflagr) 13 | - [JavaScript SDK 🔗](https://github.com/openflagr/jsflagr) 14 | - [Python SDK 🔗](https://github.com/openflagr/pyflagr) 15 | -------------------------------------------------------------------------------- /docs/api_docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Flagr API 5 | 6 | 7 | 8 | 9 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/flagr_debugging.md: -------------------------------------------------------------------------------- 1 | # Flagr Debug Console 2 | 3 | One can debug the Flagr evaluation using the debug console. 4 | Debug console is a frontend component that wraps the evaluation API. 5 | It's attached inside each flag page, and it helps to test and try the flag settings 6 | with entities. 7 | 8 | ![debugging console demo](/images/demo_debugging_console.png) 9 | -------------------------------------------------------------------------------- /docs/home.md: -------------------------------------------------------------------------------- 1 | # Get Started 2 | 3 | Flagr is an open source Go service that delivers the right experience to the right entity and monitors the impact. It provides feature flags, experimentation (A/B testing), and dynamic configuration. It has clear swagger REST APIs for flags management and flag evaluation. For more details, see [Flagr Overview](flagr_overview) 4 | 5 | ## Run 6 | 7 | Run directly with docker. 8 | 9 | ```bash 10 | # Start the docker container 11 | docker pull ghcr.io/openflagr/flagr 12 | docker run -it -p 18000:18000 ghcr.io/openflagr/flagr 13 | 14 | # Open the Flagr UI 15 | open localhost:18000 16 | ``` 17 | 18 | ## Deploy 19 | 20 | We recommend directly use the openflagr/flagr image, and configure everything in the env variables. See more in [Server Configuration](flagr_env). 21 | 22 | ```bash 23 | # Set env variables. For example, 24 | export HOST=0.0.0.0 25 | export PORT=18000 26 | export FLAGR_DB_DBDRIVER=mysql 27 | export FLAGR_DB_DBCONNECTIONSTR=root:@tcp(127.0.0.1:18100)/flagr?parseTime=true 28 | 29 | # Run the docker image. Ideally, the deployment will be handled by Kubernetes or Mesos. 30 | docker run -it -p 18000:18000 ghcr.io/openflagr/flagr 31 | ``` 32 | 33 | ## Development 34 | 35 | Install Dependencies. 36 | 37 | - Go (1.24+) 38 | - Make (for Makefile) 39 | - NPM (for building UI) 40 | 41 | Build from source. 42 | 43 | ```bash 44 | # get the source 45 | go get -u github.com/openflagr/flagr 46 | 47 | # install dependencies, generated code, and start the service in 48 | # development mode 49 | cd $GOPATH/src/github.com/openflagr/flagr 50 | make build start 51 | ``` 52 | 53 | If you just want to run the pre-built backend (without the UI development service): 54 | 55 | ``` 56 | make run 57 | ``` 58 | 59 | And alternatively to just run the UI service: 60 | 61 | ``` 62 | make run_ui 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/images/demo_debugging_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_debugging_console.png -------------------------------------------------------------------------------- /docs/images/demo_dynamic_configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_dynamic_configuration.png -------------------------------------------------------------------------------- /docs/images/demo_exp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_exp1.png -------------------------------------------------------------------------------- /docs/images/demo_exp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_exp2.png -------------------------------------------------------------------------------- /docs/images/demo_ff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_ff.png -------------------------------------------------------------------------------- /docs/images/demo_homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_homepage.png -------------------------------------------------------------------------------- /docs/images/demo_readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/demo_readme.png -------------------------------------------------------------------------------- /docs/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/favicon.png -------------------------------------------------------------------------------- /docs/images/flagr_arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_arch.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_1.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_2.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_3.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_4.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_5.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_6.png -------------------------------------------------------------------------------- /docs/images/flagr_running_example_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/flagr_running_example_7.png -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openflagr/flagr/67341a86c1064491357d7d8057e5377b6817092c/docs/images/logo.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 12 | 13 | 14 | 32 | 33 | 34 | 35 | 36 |
37 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /integration_tests/Dockerfile-Integration-Test: -------------------------------------------------------------------------------- 1 | FROM golang:1.24-alpine as go_builder 2 | WORKDIR /go/src/github.com/openflagr/flagr 3 | RUN apk add --no-cache git make build-base 4 | ADD . . 5 | ENV CGO_ENABLED=0 6 | RUN make build 7 | 8 | FROM alpine 9 | 10 | COPY --from=go_builder /go/src/github.com/openflagr/flagr/flagr . 11 | 12 | ENV HOST=0.0.0.0 13 | ENV PORT=18000 14 | ENV FLAGR_DB_DBDRIVER=sqlite3 15 | ENV FLAGR_RECORDER_ENABLED=false 16 | RUN addgroup -S appgroup && adduser -S appuser -G appgroup 17 | USER appuser 18 | EXPOSE 18000 19 | 20 | CMD "./flagr" -------------------------------------------------------------------------------- /integration_tests/Makefile: -------------------------------------------------------------------------------- 1 | build-image: 2 | docker build -f ./Dockerfile-Integration-Test -t flagr_integration_tests ../ 3 | 4 | down: 5 | docker compose down -v 6 | 7 | up: 8 | docker network create flagr_integration_tests || true 9 | docker compose up -d 10 | 11 | test: 12 | docker cp ./test.sh flagr-shakedown:/app/test.sh 13 | docker compose exec -T shakedown bash ./test.sh 14 | 15 | retest: down up test 16 | -------------------------------------------------------------------------------- /integration_tests/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | 3 | networks: 4 | default: 5 | external: true 6 | name: flagr_integration_tests 7 | 8 | services: 9 | mysql: 10 | image: mysql:5.6 11 | container_name: flagr-mysql 12 | environment: 13 | MYSQL_ALLOW_EMPTY_PASSWORD: "yes" 14 | MYSQL_DATABASE: "flagr" 15 | 16 | mysql8: 17 | image: mysql:8 18 | container_name: flagr-mysql8 19 | environment: 20 | MYSQL_ALLOW_EMPTY_PASSWORD: "yes" 21 | MYSQL_DATABASE: "flagr" 22 | 23 | postgres13: 24 | image: postgres:13 25 | container_name: flagr-postgres13 26 | environment: 27 | POSTGRES_PASSWORD: "test" 28 | POSTGRES_USER: "test" 29 | POSTGRES_DB: "flagr" 30 | 31 | postgres9: 32 | image: postgres:9 33 | container_name: flagr-postgres9 34 | environment: 35 | POSTGRES_PASSWORD: "test" 36 | POSTGRES_USER: "test" 37 | POSTGRES_DB: "flagr" 38 | 39 | checkr_flagr_with_sqlite: 40 | image: checkr/flagr:1.1.12 41 | environment: 42 | FLAGR_DB_DBDRIVER: "sqlite3" 43 | FLAGR_DB_DBCONNECTIONSTR: "/tmp/flagr.sqlite3" 44 | command: sh -c "sleep 15 && ./flagr" 45 | 46 | flagr_with_sqlite: 47 | image: flagr_integration_tests 48 | environment: 49 | FLAGR_DB_DBDRIVER: "sqlite3" 50 | FLAGR_DB_DBCONNECTIONSTR: "/tmp/flagr.sqlite3" 51 | command: sh -c "sleep 15 && ./flagr" 52 | 53 | flagr_with_mysql: 54 | image: flagr_integration_tests 55 | environment: 56 | FLAGR_DB_DBDRIVER: "mysql" 57 | FLAGR_DB_DBCONNECTIONSTR: "root:@tcp(mysql:3306)/flagr?parseTime=true" 58 | command: sh -c "sleep 15 && ./flagr" 59 | 60 | flagr_with_mysql8: 61 | image: flagr_integration_tests 62 | environment: 63 | FLAGR_DB_DBDRIVER: "mysql" 64 | FLAGR_DB_DBCONNECTIONSTR: "root:@tcp(mysql8:3306)/flagr?parseTime=true" 65 | command: sh -c "sleep 15 && ./flagr" 66 | 67 | flagr_with_postgres9: 68 | image: flagr_integration_tests 69 | environment: 70 | FLAGR_DB_DBDRIVER: "postgres" 71 | FLAGR_DB_DBCONNECTIONSTR: "sslmode=disable host=postgres9 user=test password=test dbname=flagr" 72 | command: sh -c "sleep 15 && ./flagr" 73 | 74 | flagr_with_postgres13: 75 | image: flagr_integration_tests 76 | environment: 77 | FLAGR_DB_DBDRIVER: "postgres" 78 | FLAGR_DB_DBCONNECTIONSTR: "sslmode=disable host=postgres13 user=test password=test dbname=flagr" 79 | command: sh -c "sleep 15 && ./flagr" 80 | 81 | shakedown: 82 | image: zhouzhuojie/docker-shakedown 83 | container_name: flagr-shakedown 84 | command: sh -c "tail -F /dev/null" 85 | -------------------------------------------------------------------------------- /pkg/config/config_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestSetupSentry(t *testing.T) { 11 | Config.SentryEnabled = true 12 | Config.SentryEnvironment = "test" 13 | defer func() { 14 | Config.SentryEnabled = false 15 | Config.SentryEnvironment = "" 16 | }() 17 | 18 | assert.NotPanics(t, func() { setupSentry() }) 19 | } 20 | 21 | func TestSetupNewRelic(t *testing.T) { 22 | Config.NewRelicEnabled = true 23 | defer func() { 24 | Config.NewRelicEnabled = false 25 | }() 26 | 27 | assert.Panics(t, func() { setupNewrelic() }) 28 | } 29 | 30 | func TestSetupStatsd(t *testing.T) { 31 | Config.StatsdEnabled = true 32 | defer func() { 33 | Config.StatsdEnabled = false 34 | }() 35 | 36 | assert.NotPanics(t, func() { setupStatsd() }) 37 | } 38 | 39 | func TestSetupPrometheus(t *testing.T) { 40 | prometheus.DefaultRegisterer = prometheus.NewRegistry() 41 | setupPrometheus() 42 | assert.Nil(t, Global.Prometheus.EvalCounter) 43 | 44 | Config.PrometheusEnabled = true 45 | defer func() { Config.PrometheusEnabled = false }() 46 | setupPrometheus() 47 | assert.NotNil(t, Global.Prometheus.EvalCounter) 48 | assert.NotNil(t, Global.Prometheus.RequestCounter) 49 | assert.Nil(t, Global.Prometheus.RequestHistogram) 50 | } 51 | 52 | func TestSetupPrometheusWithLatencies(t *testing.T) { 53 | prometheus.DefaultRegisterer = prometheus.NewRegistry() 54 | Config.PrometheusEnabled = true 55 | Config.PrometheusIncludeLatencyHistogram = true 56 | defer func() { 57 | Config.PrometheusEnabled = false 58 | Config.PrometheusIncludeLatencyHistogram = false 59 | }() 60 | 61 | setupPrometheus() 62 | assert.NotNil(t, Global.Prometheus.EvalCounter) 63 | assert.NotNil(t, Global.Prometheus.RequestCounter) 64 | assert.NotNil(t, Global.Prometheus.RequestHistogram) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/entity/db_test.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/openflagr/flagr/pkg/config" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func setTestDBConfig(driver string, connectionStr string) (reset func()) { 11 | old := config.Config 12 | 13 | config.Config.DBDriver = driver 14 | config.Config.DBConnectionStr = connectionStr 15 | config.Config.DBConnectionRetryAttempts = 2 16 | 17 | return func() { 18 | config.Config = old 19 | } 20 | } 21 | 22 | func TestConnectDB(t *testing.T) { 23 | t.Run("happy code path", func(t *testing.T) { 24 | reset := setTestDBConfig("sqlite3", ":memory:") 25 | defer reset() 26 | 27 | db, err := connectDB() 28 | assert.NotNil(t, db) 29 | assert.NoError(t, err) 30 | }) 31 | 32 | t.Run("error code path", func(t *testing.T) { 33 | reset := setTestDBConfig("mysql", "invalid") 34 | defer reset() 35 | 36 | _, err := connectDB() 37 | assert.Error(t, err) 38 | }) 39 | } 40 | 41 | func TestGetDB(t *testing.T) { 42 | reset := setTestDBConfig("sqlite3", ":memory:") 43 | defer reset() 44 | 45 | db := GetDB() 46 | assert.NotNil(t, db) 47 | } 48 | -------------------------------------------------------------------------------- /pkg/entity/evaluator.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // EvalContext represents the context we can evaluate and log 8 | type EvalContext struct { 9 | EntityID string 10 | EntityType string 11 | EntityContext map[string]interface{} 12 | 13 | EnableDebug bool 14 | } 15 | 16 | // EvalResult represents the result of the evaluation 17 | type EvalResult struct { 18 | FlagID uint 19 | SegmentID uint 20 | VariantID uint 21 | EvalContext EvalContext 22 | Timestamp time.Time 23 | 24 | EvalDebugLog *EvalDebugLog 25 | } 26 | 27 | // EvalDebugLog is the debugging log of evaluation 28 | type EvalDebugLog struct { 29 | SegmentDebugLogs []SegmentDebugLog 30 | Msg string 31 | } 32 | 33 | // SegmentDebugLog is the segmebnt level of debugging logs 34 | type SegmentDebugLog struct { 35 | SegmentID uint 36 | Msg string 37 | } 38 | -------------------------------------------------------------------------------- /pkg/entity/fixture.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "github.com/openflagr/flagr/swagger_gen/models" 5 | 6 | "gorm.io/gorm" 7 | ) 8 | 9 | // GenFixtureFlag is a fixture 10 | func GenFixtureFlag() Flag { 11 | f := Flag{ 12 | Model: gorm.Model{ID: 100}, 13 | Key: "flag_key_100", 14 | Description: "", 15 | Enabled: true, 16 | Segments: []Segment{GenFixtureSegment()}, 17 | Variants: []Variant{ 18 | { 19 | Model: gorm.Model{ID: 300}, 20 | FlagID: 100, 21 | Key: "control", 22 | }, 23 | { 24 | Model: gorm.Model{ID: 301}, 25 | FlagID: 100, 26 | Key: "treatment", 27 | Attachment: map[string]interface{}{ 28 | "value": "321", 29 | }, 30 | }, 31 | }, 32 | Tags: []Tag{ 33 | { 34 | Value: "tag1", 35 | }, 36 | { 37 | Value: "tag2", 38 | }, 39 | }, 40 | } 41 | f.PrepareEvaluation() 42 | return f 43 | } 44 | 45 | // GenFixtureSegment is a fixture 46 | func GenFixtureSegment() Segment { 47 | s := Segment{ 48 | Model: gorm.Model{ID: 200}, 49 | FlagID: 100, 50 | Description: "", 51 | Rank: 0, 52 | RolloutPercent: 100, 53 | Constraints: []Constraint{ 54 | { 55 | Model: gorm.Model{ID: 500}, 56 | SegmentID: 200, 57 | Property: "dl_state", 58 | Operator: models.ConstraintOperatorEQ, 59 | Value: `"CA"`, 60 | }, 61 | }, 62 | Distributions: []Distribution{ 63 | { 64 | Model: gorm.Model{ID: 400}, 65 | SegmentID: 200, 66 | VariantID: 300, 67 | VariantKey: "control", 68 | Percent: 50, 69 | }, 70 | { 71 | Model: gorm.Model{ID: 401}, 72 | SegmentID: 200, 73 | VariantID: 301, 74 | VariantKey: "treatment", 75 | Percent: 50, 76 | }, 77 | }, 78 | } 79 | s.PrepareEvaluation() 80 | return s 81 | } 82 | -------------------------------------------------------------------------------- /pkg/entity/flag_entity_type.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "gorm.io/gorm" 4 | 5 | // FlagEntityType is the entity_type that will overwrite into evaluation logs. 6 | type FlagEntityType struct { 7 | gorm.Model 8 | Key string `gorm:"type:varchar(64);uniqueIndex:flag_entity_type_key"` 9 | } 10 | -------------------------------------------------------------------------------- /pkg/entity/flag_snapshot.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "fmt" 5 | 6 | "encoding/json" 7 | 8 | "github.com/openflagr/flagr/pkg/config" 9 | "github.com/openflagr/flagr/pkg/util" 10 | "github.com/sirupsen/logrus" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | // FlagSnapshot is the snapshot of a flag 15 | // Any change of the flag will create a new snapshot 16 | type FlagSnapshot struct { 17 | gorm.Model 18 | FlagID uint `gorm:"index:idx_flagsnapshot_flagid"` 19 | UpdatedBy string 20 | Flag []byte `gorm:"type:text"` 21 | } 22 | 23 | // SaveFlagSnapshot saves the Flag Snapshot 24 | func SaveFlagSnapshot(db *gorm.DB, flagID uint, updatedBy string) { 25 | tx := db.Begin() 26 | f := &Flag{} 27 | if err := tx.First(f, flagID).Error; err != nil { 28 | logrus.WithFields(logrus.Fields{ 29 | "err": err, 30 | "flagID": flagID, 31 | }).Error("failed to find the flag when SaveFlagSnapshot") 32 | return 33 | } 34 | f.Preload(tx) 35 | 36 | b, err := json.Marshal(f) 37 | if err != nil { 38 | logrus.WithFields(logrus.Fields{ 39 | "err": err, 40 | "flagID": flagID, 41 | }).Error("failed to marshal the flag into JSON when SaveFlagSnapshot") 42 | return 43 | } 44 | 45 | fs := FlagSnapshot{FlagID: f.Model.ID, UpdatedBy: updatedBy, Flag: b} 46 | if err := tx.Create(&fs).Error; err != nil { 47 | logrus.WithFields(logrus.Fields{ 48 | "err": err, 49 | "flagID": f.Model.ID, 50 | }).Error("failed to save FlagSnapshot") 51 | tx.Rollback() 52 | return 53 | } 54 | 55 | f.UpdatedBy = updatedBy 56 | f.SnapshotID = fs.Model.ID 57 | 58 | if err := tx.Save(f).Error; err != nil { 59 | logrus.WithFields(logrus.Fields{ 60 | "err": err, 61 | "flagID": f.Model.ID, 62 | "flagSnapshotID": fs.Model.ID, 63 | }).Error("failed to save Flag's UpdatedBy and SnapshotID") 64 | tx.Rollback() 65 | return 66 | } 67 | 68 | if err := tx.Commit().Error; err != nil { 69 | tx.Rollback() 70 | } 71 | 72 | logFlagSnapshotUpdate(flagID, updatedBy) 73 | } 74 | 75 | var logFlagSnapshotUpdate = func(flagID uint, updatedBy string) { 76 | if config.Global.StatsdClient == nil { 77 | return 78 | } 79 | 80 | config.Global.StatsdClient.Incr( 81 | "flag.snapshot.updated", 82 | []string{ 83 | fmt.Sprintf("FlagID:%d", flagID), 84 | fmt.Sprintf("UpdatedBy:%s", util.SafeStringWithDefault(updatedBy, "null")), 85 | }, 86 | float64(1), 87 | ) 88 | } 89 | -------------------------------------------------------------------------------- /pkg/entity/flag_snapshot_test.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSaveFlagSnapshot(t *testing.T) { 8 | f := GenFixtureFlag() 9 | db := PopulateTestDB(f) 10 | 11 | tmpDB, dbErr := db.DB() 12 | if dbErr != nil { 13 | t.Errorf("Failed to get database") 14 | } 15 | 16 | defer tmpDB.Close() 17 | 18 | t.Run("happy code path", func(t *testing.T) { 19 | SaveFlagSnapshot(db, f.Model.ID, "flagr-test@example.com") 20 | }) 21 | 22 | t.Run("save on non-existing flag", func(t *testing.T) { 23 | SaveFlagSnapshot(db, uint(999999), "flagr-test@example.com") 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/entity/flag_test.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestFlagPrepareEvaluation(t *testing.T) { 10 | t.Run("happy code path", func(t *testing.T) { 11 | f := GenFixtureFlag() 12 | assert.NoError(t, f.PrepareEvaluation()) 13 | assert.NotNil(t, f.FlagEvaluation.VariantsMap) 14 | assert.NotNil(t, f.Tags) 15 | }) 16 | } 17 | 18 | func TestFlagPreload(t *testing.T) { 19 | t.Run("happy code path", func(t *testing.T) { 20 | f := GenFixtureFlag() 21 | db := PopulateTestDB(f) 22 | 23 | tmpDB, dbErr := db.DB() 24 | if dbErr != nil { 25 | t.Errorf("Failed to get database") 26 | } 27 | 28 | defer tmpDB.Close() 29 | 30 | err := f.Preload(db) 31 | assert.NoError(t, err) 32 | }) 33 | } 34 | 35 | func TestFlagPreloadTags(t *testing.T) { 36 | t.Run("happy code path", func(t *testing.T) { 37 | f := GenFixtureFlag() 38 | db := PopulateTestDB(f) 39 | 40 | tmpDB, dbErr := db.DB() 41 | if dbErr != nil { 42 | t.Errorf("Failed to get database") 43 | } 44 | 45 | defer tmpDB.Close() 46 | 47 | err := f.PreloadTags(db) 48 | assert.NoError(t, err) 49 | }) 50 | } 51 | 52 | func TestCreateFlagKey(t *testing.T) { 53 | t.Run("happy code path", func(t *testing.T) { 54 | key, err := CreateFlagKey("") 55 | assert.NoError(t, err) 56 | assert.NotZero(t, key) 57 | }) 58 | 59 | t.Run("invalid key", func(t *testing.T) { 60 | key, err := CreateFlagKey(" spaces in key are not allowed 1-2-3") 61 | assert.Error(t, err) 62 | assert.Zero(t, key) 63 | }) 64 | } 65 | 66 | func TestCreateFlagEntityType(t *testing.T) { 67 | t.Run("happy code path", func(t *testing.T) { 68 | f := GenFixtureFlag() 69 | db := PopulateTestDB(f) 70 | 71 | err := CreateFlagEntityType(db, "") 72 | assert.NoError(t, err) 73 | }) 74 | 75 | t.Run("invalid key", func(t *testing.T) { 76 | f := GenFixtureFlag() 77 | db := PopulateTestDB(f) 78 | 79 | err := CreateFlagEntityType(db, " spaces in key are not allowed 123-invalid-key") 80 | assert.Error(t, err) 81 | }) 82 | } 83 | -------------------------------------------------------------------------------- /pkg/entity/logger.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | logrus "github.com/sirupsen/logrus" 8 | gorm_logger "gorm.io/gorm/logger" 9 | ) 10 | 11 | type Logger struct { 12 | LogLevel gorm_logger.LogLevel 13 | SlowThreshold time.Duration 14 | IgnoreRecordNotFoundError bool 15 | } 16 | 17 | func (l *Logger) LogMode(level gorm_logger.LogLevel) gorm_logger.Interface { 18 | newlogger := *l 19 | newlogger.LogLevel = level 20 | return &newlogger 21 | } 22 | 23 | func (l *Logger) Info(ctx context.Context, s string, args ...interface{}) { 24 | logrus.WithContext(ctx).Infof(s, args...) 25 | } 26 | 27 | func (l *Logger) Warn(ctx context.Context, s string, args ...interface{}) { 28 | logrus.WithContext(ctx).Warnf(s, args...) 29 | } 30 | 31 | func (l *Logger) Error(ctx context.Context, s string, args ...interface{}) { 32 | logrus.WithContext(ctx).Errorf(s, args...) 33 | } 34 | 35 | func (l *Logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { 36 | if logrus.GetLevel() >= logrus.TraceLevel { 37 | sql, _ := fc() 38 | elapsed := time.Since(begin) 39 | if elapsed > l.SlowThreshold { 40 | logrus.WithContext(ctx).Tracef("%s [%s]", sql, elapsed) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pkg/entity/segment.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "github.com/zhouzhuojie/conditions" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | // SegmentDefaultRank is the default rank when we create the segment 9 | const SegmentDefaultRank = uint(999) 10 | 11 | // Segment is the unit of segmentation 12 | type Segment struct { 13 | gorm.Model 14 | FlagID uint `gorm:"index:idx_segment_flagid"` 15 | Description string `gorm:"type:text"` 16 | Rank uint 17 | RolloutPercent uint 18 | Constraints ConstraintArray 19 | Distributions []Distribution 20 | 21 | // Purely for evaluation 22 | SegmentEvaluation SegmentEvaluation `gorm:"-" json:"-"` 23 | } 24 | 25 | // PreloadConstraintsDistribution preloads constraints and distributions 26 | // for segment 27 | func PreloadConstraintsDistribution(db *gorm.DB) *gorm.DB { 28 | return db. 29 | Preload("Distributions", func(db *gorm.DB) *gorm.DB { 30 | return db.Order("variant_id") 31 | }). 32 | Preload("Constraints", func(db *gorm.DB) *gorm.DB { 33 | return db.Order("created_at") 34 | }) 35 | } 36 | 37 | // Preload preloads the segment 38 | func (s *Segment) Preload(db *gorm.DB) error { 39 | return PreloadConstraintsDistribution(db).First(s, s.Model.ID).Error 40 | } 41 | 42 | // SegmentEvaluation is a struct that holds the necessary info for evaluation 43 | type SegmentEvaluation struct { 44 | ConditionsExpr conditions.Expr 45 | DistributionArray DistributionArray 46 | } 47 | 48 | // PrepareEvaluation prepares the segment for evaluation by parsing constraints 49 | // and denormalize distributions 50 | func (s *Segment) PrepareEvaluation() error { 51 | dLen := len(s.Distributions) 52 | se := SegmentEvaluation{ 53 | DistributionArray: DistributionArray{ 54 | VariantIDs: make([]uint, dLen), 55 | PercentsAccumulated: make([]int, dLen), 56 | }, 57 | } 58 | 59 | if len(s.Constraints) != 0 { 60 | expr, err := s.Constraints.ToExpr() 61 | if err != nil { 62 | return err 63 | } 64 | se.ConditionsExpr = expr 65 | } 66 | 67 | for i, d := range s.Distributions { 68 | se.DistributionArray.VariantIDs[i] = d.VariantID 69 | if i == 0 { 70 | se.DistributionArray.PercentsAccumulated[i] = int(d.Percent * PercentMultiplier) 71 | } else { 72 | se.DistributionArray.PercentsAccumulated[i] = se.DistributionArray.PercentsAccumulated[i-1] + int(d.Percent*PercentMultiplier) 73 | } 74 | } 75 | 76 | s.SegmentEvaluation = se 77 | return nil 78 | } 79 | -------------------------------------------------------------------------------- /pkg/entity/segment_test.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestSegmentPrepareEvaluation(t *testing.T) { 10 | t.Run("happy code path", func(t *testing.T) { 11 | s := GenFixtureSegment() 12 | assert.NoError(t, s.PrepareEvaluation()) 13 | assert.NotNil(t, s.SegmentEvaluation.ConditionsExpr) 14 | assert.NotNil(t, s.SegmentEvaluation.DistributionArray) 15 | }) 16 | 17 | t.Run("error code path", func(t *testing.T) { 18 | s := GenFixtureSegment() 19 | s.SegmentEvaluation = SegmentEvaluation{} 20 | s.Constraints[0].Value = `"CA"]` // invalid value 21 | assert.Error(t, s.PrepareEvaluation()) 22 | assert.Empty(t, s.SegmentEvaluation.ConditionsExpr) 23 | assert.Empty(t, s.SegmentEvaluation.DistributionArray.VariantIDs) 24 | assert.Empty(t, s.SegmentEvaluation.DistributionArray.PercentsAccumulated) 25 | }) 26 | } 27 | 28 | func TestSegmentPreload(t *testing.T) { 29 | t.Run("happy code path", func(t *testing.T) { 30 | s := GenFixtureSegment() 31 | f := GenFixtureFlag() 32 | db := PopulateTestDB(f) 33 | 34 | tmpDB, dbErr := db.DB() 35 | if dbErr != nil { 36 | t.Errorf("Failed to get database") 37 | } 38 | 39 | defer tmpDB.Close() 40 | 41 | err := s.Preload(db) 42 | assert.NoError(t, err) 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/entity/tag.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | ) 6 | 7 | // Tag is a descriptive identifier given to ease searchability 8 | type Tag struct { 9 | gorm.Model 10 | 11 | Value string `gorm:"type:varchar(64);uniqueIndex:idx_tag_value"` 12 | Flags []*Flag `gorm:"many2many:flags_tags;"` 13 | } 14 | -------------------------------------------------------------------------------- /pkg/entity/user.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "gorm.io/gorm" 4 | 5 | // User represents the User struct 6 | type User struct { 7 | gorm.Model 8 | Email string `gorm:"type:text"` 9 | } 10 | -------------------------------------------------------------------------------- /pkg/entity/variant.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "database/sql/driver" 5 | "fmt" 6 | 7 | "encoding/json" 8 | 9 | "github.com/openflagr/flagr/pkg/util" 10 | "github.com/spf13/cast" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | // Variant is the struct that represent the experience/variant of the evaluation entity 15 | type Variant struct { 16 | gorm.Model 17 | FlagID uint `gorm:"index:idx_variant_flagid"` 18 | Key string 19 | Attachment Attachment `gorm:"type:text"` 20 | } 21 | 22 | // Validate validates the Variant 23 | func (v *Variant) Validate() error { 24 | ok, msg := util.IsSafeKey(v.Key) 25 | if !ok { 26 | return fmt.Errorf("%s", msg) 27 | } 28 | return nil 29 | } 30 | 31 | // Attachment supports dynamic configuration in variant 32 | type Attachment map[string]interface{} 33 | 34 | // Scan implements scanner interface 35 | func (a *Attachment) Scan(value interface{}) error { 36 | if value == nil { 37 | return nil 38 | } 39 | s := cast.ToString(value) 40 | if err := json.Unmarshal([]byte(s), a); err != nil { 41 | return fmt.Errorf("cannot scan %v into Attachment type. err: %v", value, err) 42 | } 43 | return nil 44 | } 45 | 46 | // Value implements valuer interface 47 | func (a Attachment) Value() (driver.Value, error) { 48 | bytes, err := json.Marshal(a) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return string(bytes), nil 53 | } 54 | -------------------------------------------------------------------------------- /pkg/entity/variant_test.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "gorm.io/gorm" 8 | ) 9 | 10 | func TestValidate(t *testing.T) { 11 | t.Run("empty case", func(t *testing.T) { 12 | v := Variant{} 13 | err := v.Validate() 14 | assert.Error(t, err) 15 | }) 16 | t.Run("happy code path", func(t *testing.T) { 17 | v := Variant{ 18 | Model: gorm.Model{}, 19 | FlagID: 0, 20 | Key: "a123", 21 | Attachment: nil, 22 | } 23 | err := v.Validate() 24 | assert.NoError(t, err) 25 | }) 26 | } 27 | 28 | func TestVariantScan(t *testing.T) { 29 | t.Run("happy code path", func(t *testing.T) { 30 | a := &Attachment{} 31 | err := a.Scan([]byte(`{"key": "value"}`)) 32 | assert.NoError(t, err) 33 | }) 34 | 35 | t.Run("nil value", func(t *testing.T) { 36 | a := &Attachment{} 37 | err := a.Scan(nil) 38 | assert.NoError(t, err) 39 | }) 40 | 41 | t.Run("invalid json", func(t *testing.T) { 42 | a := &Attachment{} 43 | err := a.Scan([]byte(`{`)) 44 | assert.Error(t, err) 45 | }) 46 | 47 | t.Run("invalid value type", func(t *testing.T) { 48 | a := &Attachment{} 49 | err := a.Scan(123) 50 | assert.Error(t, err) 51 | }) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/handler/data_record_frame_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/openflagr/flagr/swagger_gen/models" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestFrameOutput(t *testing.T) { 11 | er := models.EvalResult{ 12 | EvalContext: &models.EvalContext{ 13 | EntityID: "123", 14 | }, 15 | FlagID: 1, 16 | FlagSnapshotID: 1, 17 | SegmentID: 1, 18 | VariantID: 1, 19 | VariantKey: "control", 20 | } 21 | 22 | t.Run("empty options", func(t *testing.T) { 23 | frame := DataRecordFrame{ 24 | evalResult: er, 25 | options: DataRecordFrameOptions{}, 26 | } 27 | output, err := frame.Output() 28 | assert.NoError(t, err) 29 | assert.Contains(t, string(output), "123") 30 | assert.Contains(t, string(output), "payload") 31 | }) 32 | 33 | t.Run("payload with encryption options", func(t *testing.T) { 34 | frame := DataRecordFrame{ 35 | evalResult: er, 36 | options: DataRecordFrameOptions{ 37 | Encrypted: true, 38 | Encryptor: newSimpleboxEncryptor("fake_key"), 39 | FrameOutputMode: "payload", 40 | }, 41 | } 42 | output, err := frame.Output() 43 | assert.NoError(t, err) 44 | assert.Contains(t, string(output), "payload") 45 | }) 46 | 47 | t.Run("payload_raw_json options", func(t *testing.T) { 48 | frame := DataRecordFrame{ 49 | evalResult: er, 50 | options: DataRecordFrameOptions{ 51 | Encrypted: false, 52 | Encryptor: nil, 53 | FrameOutputMode: frameOutputModePayloadRawJSON, 54 | }, 55 | } 56 | output, err := frame.Output() 57 | assert.NoError(t, err) 58 | assert.Contains(t, string(output), "123") 59 | assert.Contains(t, string(output), "payload") 60 | assert.NotContains(t, string(output), `"payload":""`) 61 | }) 62 | } 63 | 64 | func TestGetPartitionKey(t *testing.T) { 65 | 66 | t.Run("empty evalResult", func(t *testing.T) { 67 | er := models.EvalResult{} 68 | frame := DataRecordFrame{evalResult: er} 69 | assert.Equal(t, "", frame.GetPartitionKey()) 70 | }) 71 | 72 | t.Run("happy code path evalResult", func(t *testing.T) { 73 | er := models.EvalResult{ 74 | EvalContext: &models.EvalContext{ 75 | EntityID: "123", 76 | }, 77 | FlagID: 1, 78 | FlagSnapshotID: 1, 79 | SegmentID: 1, 80 | VariantID: 1, 81 | VariantKey: "control", 82 | } 83 | frame := DataRecordFrame{evalResult: er} 84 | assert.Equal(t, "123", frame.GetPartitionKey()) 85 | }) 86 | 87 | } 88 | -------------------------------------------------------------------------------- /pkg/handler/data_recorder.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/openflagr/flagr/pkg/config" 7 | "github.com/openflagr/flagr/swagger_gen/models" 8 | ) 9 | 10 | var ( 11 | singletonDataRecorder DataRecorder 12 | singletonDataRecorderOnce sync.Once 13 | ) 14 | 15 | // DataRecorder can record and produce the evaluation result 16 | type DataRecorder interface { 17 | AsyncRecord(models.EvalResult) 18 | NewDataRecordFrame(models.EvalResult) DataRecordFrame 19 | } 20 | 21 | // GetDataRecorder gets the data recorder 22 | func GetDataRecorder() DataRecorder { 23 | singletonDataRecorderOnce.Do(func() { 24 | recorderType := config.Config.RecorderType 25 | switch recorderType { 26 | case "kafka": 27 | singletonDataRecorder = NewKafkaRecorder() 28 | case "kinesis": 29 | singletonDataRecorder = NewKinesisRecorder() 30 | case "pubsub": 31 | singletonDataRecorder = NewPubsubRecorder() 32 | default: 33 | panic("recorderType not supported") 34 | } 35 | }) 36 | 37 | return singletonDataRecorder 38 | } 39 | -------------------------------------------------------------------------------- /pkg/handler/data_recorder_kinesis_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "testing" 5 | 6 | producer "github.com/a8m/kinesis-producer" 7 | "github.com/openflagr/flagr/swagger_gen/models" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestNewKinesisRecorder(t *testing.T) { 12 | t.Run("no panics", func(t *testing.T) { 13 | assert.NotPanics(t, func() { NewKinesisRecorder() }) 14 | }) 15 | } 16 | 17 | func TestKinesisAsyncRecord(t *testing.T) { 18 | t.Run("invalid stream name", func(t *testing.T) { 19 | assert.Panics(t, func() { 20 | kr := &kinesisRecorder{ 21 | producer: newKinesisProducer(&producer.Config{}), 22 | } 23 | 24 | kr.AsyncRecord(models.EvalResult{}) 25 | }) 26 | }) 27 | 28 | t.Run("valid stream name", func(t *testing.T) { 29 | assert.NotPanics(t, func() { 30 | kr := &kinesisRecorder{ 31 | producer: newKinesisProducer(&producer.Config{StreamName: "hallo"}), 32 | } 33 | 34 | kr.AsyncRecord( 35 | models.EvalResult{ 36 | EvalContext: &models.EvalContext{ 37 | EntityID: "d08042018", 38 | }, 39 | FlagID: 1, 40 | FlagSnapshotID: 1, 41 | SegmentID: 1, 42 | VariantID: 1, 43 | VariantKey: "control", 44 | }, 45 | ) 46 | }) 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /pkg/handler/data_recorder_pubsub.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "context" 5 | 6 | "cloud.google.com/go/pubsub" 7 | "github.com/openflagr/flagr/pkg/config" 8 | "github.com/openflagr/flagr/swagger_gen/models" 9 | "github.com/sirupsen/logrus" 10 | "google.golang.org/api/option" 11 | ) 12 | 13 | type pubsubRecorder struct { 14 | producer *pubsub.Client 15 | topic *pubsub.Topic 16 | options DataRecordFrameOptions 17 | } 18 | 19 | var ( 20 | pubsubClient = func() (*pubsub.Client, error) { 21 | return pubsub.NewClient( 22 | context.Background(), 23 | config.Config.RecorderPubsubProjectID, 24 | option.WithCredentialsFile(config.Config.RecorderPubsubKeyFile), 25 | ) 26 | } 27 | ) 28 | 29 | // NewPubsubRecorder creates a new Pubsub recorder 30 | var NewPubsubRecorder = func() DataRecorder { 31 | client, err := pubsubClient() 32 | if err != nil { 33 | logrus.WithField("pubsub_error", err).Fatal("error getting pubsub client") 34 | } 35 | 36 | return &pubsubRecorder{ 37 | producer: client, 38 | topic: client.Topic(config.Config.RecorderPubsubTopicName), 39 | options: DataRecordFrameOptions{ 40 | Encrypted: false, // not implemented yet 41 | FrameOutputMode: config.Config.RecorderFrameOutputMode, 42 | }, 43 | } 44 | } 45 | 46 | func (p *pubsubRecorder) NewDataRecordFrame(r models.EvalResult) DataRecordFrame { 47 | return DataRecordFrame{ 48 | evalResult: r, 49 | options: p.options, 50 | } 51 | } 52 | 53 | func (p *pubsubRecorder) AsyncRecord(r models.EvalResult) { 54 | frame := p.NewDataRecordFrame(r) 55 | output, err := frame.Output() 56 | if err != nil { 57 | logrus.WithField("err", err).Error("failed to generate data record frame for pubsub recorder") 58 | return 59 | } 60 | ctx := context.Background() 61 | res := p.topic.Publish(ctx, &pubsub.Message{Data: output}) 62 | if config.Config.RecorderPubsubVerbose { 63 | go func() { 64 | ctx, cancel := context.WithTimeout(ctx, config.Config.RecorderPubsubVerboseCancelTimeout) 65 | defer cancel() 66 | id, err := res.Get(ctx) 67 | if err != nil { 68 | logrus.WithFields(logrus.Fields{"pubsub_error": err, "id": id}).Error("error pushing to pubsub") 69 | } 70 | }() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /pkg/handler/data_recorder_pubsub_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "cloud.google.com/go/pubsub" 8 | "cloud.google.com/go/pubsub/pstest" 9 | "github.com/openflagr/flagr/swagger_gen/models" 10 | "github.com/prashantv/gostub" 11 | "github.com/stretchr/testify/assert" 12 | "google.golang.org/api/option" 13 | "google.golang.org/grpc" 14 | "google.golang.org/grpc/credentials/insecure" 15 | ) 16 | 17 | func TestNewPubsubRecorder(t *testing.T) { 18 | t.Run("no panics", func(t *testing.T) { 19 | client := mockClient(t) 20 | defer client.Close() 21 | 22 | defer gostub.StubFunc( 23 | &pubsubClient, 24 | client, 25 | nil, 26 | ).Reset() 27 | 28 | assert.NotPanics(t, func() { NewPubsubRecorder() }) 29 | }) 30 | } 31 | 32 | func TestPubsubAsyncRecord(t *testing.T) { 33 | t.Run("enabled and valid", func(t *testing.T) { 34 | client := mockClient(t) 35 | defer client.Close() 36 | topic := client.Topic("test") 37 | assert.NotPanics(t, func() { 38 | pr := &pubsubRecorder{ 39 | producer: client, 40 | topic: topic, 41 | } 42 | 43 | pr.AsyncRecord( 44 | models.EvalResult{ 45 | EvalContext: &models.EvalContext{ 46 | EntityID: "d08042018", 47 | }, 48 | FlagID: 1, 49 | FlagSnapshotID: 1, 50 | SegmentID: 1, 51 | VariantID: 1, 52 | VariantKey: "control", 53 | }, 54 | ) 55 | }) 56 | }) 57 | } 58 | 59 | func mockClient(t *testing.T) *pubsub.Client { 60 | ctx := context.Background() 61 | srv := pstest.NewServer() 62 | defer srv.Close() 63 | conn, err := grpc.Dial(srv.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) 64 | if err != nil { 65 | t.Fatal("cannot connect to mocked server") 66 | } 67 | defer conn.Close() 68 | client, err := pubsub.NewClient(ctx, "project", option.WithGRPCConn(conn)) 69 | 70 | if err != nil { 71 | t.Fatal("failed creating mock client", err) 72 | } 73 | 74 | return client 75 | } 76 | -------------------------------------------------------------------------------- /pkg/handler/data_recorder_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "sync" 5 | "testing" 6 | 7 | "github.com/openflagr/flagr/pkg/config" 8 | 9 | "github.com/prashantv/gostub" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestGetDataRecorder(t *testing.T) { 14 | singletonDataRecorderOnce = sync.Once{} 15 | defer gostub.StubFunc(&NewKafkaRecorder, nil).Reset() 16 | 17 | assert.NotPanics(t, func() { 18 | GetDataRecorder() 19 | }) 20 | } 21 | 22 | func TestGetDataRecorderWhenKinesisIsSet(t *testing.T) { 23 | singletonDataRecorderOnce = sync.Once{} 24 | defer gostub.StubFunc(&NewKinesisRecorder, nil).Reset() 25 | config.Config.RecorderType = "kinesis" 26 | 27 | assert.NotPanics(t, func() { 28 | GetDataRecorder() 29 | }) 30 | 31 | config.Config.RecorderType = "kafka" 32 | } 33 | 34 | func TestGetDataRecorderWhenPubsubIsSet(t *testing.T) { 35 | singletonDataRecorderOnce = sync.Once{} 36 | defer gostub.StubFunc(&NewPubsubRecorder, nil).Reset() 37 | config.Config.RecorderType = "pubsub" 38 | 39 | assert.NotPanics(t, func() { 40 | GetDataRecorder() 41 | }) 42 | 43 | config.Config.RecorderType = "kafka" 44 | } 45 | 46 | func TestGetDataRecorderPanicsWhenRecorderIsInvalid(t *testing.T) { 47 | singletonDataRecorderOnce = sync.Once{} 48 | config.Config.RecorderType = "invalid" 49 | 50 | assert.Panics(t, func() { 51 | GetDataRecorder() 52 | }) 53 | 54 | config.Config.RecorderType = "kafka" 55 | } 56 | -------------------------------------------------------------------------------- /pkg/handler/error.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/openflagr/flagr/pkg/util" 7 | "github.com/openflagr/flagr/swagger_gen/models" 8 | ) 9 | 10 | // Error is the handler error 11 | type Error struct { 12 | StatusCode int 13 | Message string 14 | Values []interface{} 15 | } 16 | 17 | func (e *Error) Error() string { 18 | msg := fmt.Sprintf(e.Message, e.Values...) 19 | return fmt.Sprintf("status_code: %d. %s", e.StatusCode, msg) 20 | } 21 | 22 | // NewError creates Error 23 | func NewError(statusCode int, msg string, values ...interface{}) *Error { 24 | return &Error{ 25 | StatusCode: statusCode, 26 | Message: msg, 27 | Values: values, 28 | } 29 | } 30 | 31 | // ErrorMessage generates error messages 32 | func ErrorMessage(s string, data ...interface{}) *models.Error { 33 | return &models.Error{ 34 | Message: util.StringPtr(fmt.Sprintf(s, data...)), 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pkg/handler/error_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestNewError(t *testing.T) { 10 | err := NewError(500, "%s some error", "err message") 11 | s := err.Error() 12 | assert.NotNil(t, err) 13 | assert.NotEmpty(t, s) 14 | } 15 | 16 | func TestErrorMessage(t *testing.T) { 17 | msg := ErrorMessage("%s some error", "err message") 18 | assert.NotNil(t, msg) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/handler/eval_cache_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "github.com/openflagr/flagr/swagger_gen/models" 5 | "testing" 6 | 7 | "github.com/openflagr/flagr/pkg/entity" 8 | 9 | "github.com/prashantv/gostub" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestGetByFlagKeyOrID(t *testing.T) { 14 | fixtureFlag := entity.GenFixtureFlag() 15 | db := entity.PopulateTestDB(fixtureFlag) 16 | 17 | tmpDB, dbErr := db.DB() 18 | if dbErr != nil { 19 | t.Errorf("Failed to get database") 20 | } 21 | 22 | defer tmpDB.Close() 23 | defer gostub.StubFunc(&getDB, db).Reset() 24 | 25 | ec := GetEvalCache() 26 | ec.reloadMapCache() 27 | f := ec.GetByFlagKeyOrID(fixtureFlag.ID) 28 | assert.Equal(t, f.ID, fixtureFlag.ID) 29 | assert.Equal(t, f.Tags[0].Value, fixtureFlag.Tags[0].Value) 30 | } 31 | 32 | func TestGetByTags(t *testing.T) { 33 | fixtureFlag := entity.GenFixtureFlag() 34 | db := entity.PopulateTestDB(fixtureFlag) 35 | 36 | tmpDB, dbErr := db.DB() 37 | if dbErr != nil { 38 | t.Errorf("Failed to get database") 39 | } 40 | 41 | defer tmpDB.Close() 42 | defer gostub.StubFunc(&getDB, db).Reset() 43 | 44 | ec := GetEvalCache() 45 | ec.reloadMapCache() 46 | 47 | tags := make([]string, len(fixtureFlag.Tags)) 48 | for i, s := range fixtureFlag.Tags { 49 | tags[i] = s.Value 50 | } 51 | any := models.EvalContextFlagTagsOperatorANY 52 | all := models.EvalContextFlagTagsOperatorALL 53 | f := ec.GetByTags(tags, &any) 54 | assert.Len(t, f, 1) 55 | assert.Equal(t, f[0].ID, fixtureFlag.ID) 56 | assert.Equal(t, f[0].Tags[0].Value, fixtureFlag.Tags[0].Value) 57 | 58 | tags = make([]string, len(fixtureFlag.Tags)+1) 59 | for i, s := range fixtureFlag.Tags { 60 | tags[i] = s.Value 61 | } 62 | tags[len(tags)-1] = "tag3" 63 | 64 | f = ec.GetByTags(tags, &any) 65 | assert.Len(t, f, 1) 66 | 67 | var operator *string 68 | f = ec.GetByTags(tags, operator) 69 | assert.Len(t, f, 1) 70 | 71 | f = ec.GetByTags(tags, &all) 72 | assert.Len(t, f, 0) 73 | } 74 | -------------------------------------------------------------------------------- /pkg/handler/fixture.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "github.com/openflagr/flagr/pkg/entity" 5 | "github.com/openflagr/flagr/pkg/util" 6 | ) 7 | 8 | // GenFixtureEvalCache generates a fixture 9 | func GenFixtureEvalCache() *EvalCache { 10 | f := entity.GenFixtureFlag() 11 | 12 | tagCache := make(map[string]map[uint]*entity.Flag) 13 | for _, tag := range f.Tags { 14 | tagCache[tag.Value] = map[uint]*entity.Flag{f.ID: &f} 15 | } 16 | 17 | ec := &EvalCache{ 18 | cache: &cacheContainer{ 19 | idCache: map[string]*entity.Flag{util.SafeString(f.Model.ID): &f}, 20 | keyCache: map[string]*entity.Flag{f.Key: &f}, 21 | tagCache: tagCache, 22 | }, 23 | } 24 | 25 | return ec 26 | } 27 | -------------------------------------------------------------------------------- /pkg/handler/handler_test.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/openflagr/flagr/pkg/entity" 7 | "github.com/openflagr/flagr/swagger_gen/restapi/operations" 8 | 9 | "github.com/prashantv/gostub" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestSetup(t *testing.T) { 14 | defer gostub.StubFunc(&getDB, entity.NewTestDB()).Reset() 15 | assert.NotPanics(t, func() { 16 | Setup(&operations.FlagrAPI{}) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/handler/subject.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/openflagr/flagr/pkg/config" 7 | "github.com/openflagr/flagr/pkg/util" 8 | 9 | jwt "github.com/form3tech-oss/jwt-go" 10 | ) 11 | 12 | func getSubjectFromRequest(r *http.Request) string { 13 | if r == nil { 14 | return "" 15 | } 16 | 17 | if config.Config.JWTAuthEnabled { 18 | token, ok := r.Context().Value(config.Config.JWTAuthUserProperty).(*jwt.Token) 19 | if !ok { 20 | return "" 21 | } 22 | 23 | if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { 24 | return util.SafeString(claims[config.Config.JWTAuthUserClaim]) 25 | } 26 | 27 | } else if config.Config.HeaderAuthEnabled { 28 | return r.Header.Get(config.Config.HeaderAuthUserField) 29 | } else if config.Config.CookieAuthEnabled { 30 | c, err := r.Cookie(config.Config.CookieAuthUserField) 31 | if err != nil { 32 | return "" 33 | } 34 | if config.Config.CookieAuthUserFieldJWTClaim != "" { 35 | // for this case, we choose to skip the error check because just like HeaderAuthUserField 36 | // in the future, we can extend this function to support cookie jwt token validation 37 | // this assumes that the cookie we get already passed the auth middleware 38 | token, _ := jwt.Parse(c.Value, func(token *jwt.Token) (interface{}, error) { return "", nil }) 39 | if claims, ok := token.Claims.(jwt.MapClaims); ok { 40 | return util.SafeString(claims[config.Config.CookieAuthUserFieldJWTClaim]) 41 | } 42 | } 43 | return c.Value 44 | } 45 | 46 | return "" 47 | } 48 | -------------------------------------------------------------------------------- /pkg/handler/testdata/certificates/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGOTCCBCGgAwIBAgIJAOE/vJd8EB24MA0GCSqGSIb3DQEBBQUAMIGyMQswCQYD 3 | VQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRMwEQYDVQQHDApTdHJhc2JvdXJnMRgw 4 | FgYDVQQKDA93d3cuZnJlZWxhbi5vcmcxEDAOBgNVBAsMB2ZyZWVsYW4xLTArBgNV 5 | BAMMJEZyZWVsYW4gU2FtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTEiMCAGCSqG 6 | SIb3DQEJARYTY29udGFjdEBmcmVlbGFuLm9yZzAeFw0xMjA0MjcxMDE3NDRaFw0x 7 | MjA1MjcxMDE3NDRaMIGyMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRMw 8 | EQYDVQQHDApTdHJhc2JvdXJnMRgwFgYDVQQKDA93d3cuZnJlZWxhbi5vcmcxEDAO 9 | BgNVBAsMB2ZyZWVsYW4xLTArBgNVBAMMJEZyZWVsYW4gU2FtcGxlIENlcnRpZmlj 10 | YXRlIEF1dGhvcml0eTEiMCAGCSqGSIb3DQEJARYTY29udGFjdEBmcmVlbGFuLm9y 11 | ZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAODp+8oQcK+MTuWPZVxJ 12 | ZR75paK4zcUngupYXWSGWFXPTV7vssFk6vInePArTL+T9KwHfiZ29Pp3UbzDlysY 13 | Kz9f9Ae50jGD6xVPwXgQ/VI979GyFXzhiEMtSYykF04tBJiDl2/FZxbHPpNxC39t 14 | 14kwuDqBin9N/ZbT5+45tbbS8ziXS+QgL5hD2q2eYCWayrGEt1Y+jDAdHDHmGnZ8 15 | d4hbgILJAs3IInOCDjC4c1gwHFb8G4QHHTwVhjhqpkq2hQHgzWBC1l2Dku/oDYev 16 | Zu/pfpTo3z6+NOYBrUWseQmIuG+DGMQA9KOuSQveyTywBm4G4vZKn0sCu1/v2+9T 17 | BGv41tgS/Yf6oeeQVrbS4RFY1r9qTK6DW9wkTTesa4xoDKQrWjSJ7+aa8tvBXLGX 18 | x2xdRNWLeRMuGBSOihwXmDr+rCJRauT7pItN5X+uWNTX1ofNksQSUMaFJ5K7L0LU 19 | iQqU2Yyt/8UphdVZL4EFkGSA13UDWtb9mM1hY0h65LlSYwCchEphrtI9cuV+ITrS 20 | NcN6cP/dqDx1/jWd6dqjNu7+dugwX5elQS9uUYCFmugR5s1m2eeBg3QuC7gZLE0N 21 | NbgS7oSxKJe9KeOcw68jHWfBKsCfBfQ4fU2t/ntMybT3hCdEMQu4dgM5Tyw/UeFq 22 | 0SaJyTl+G1bTzS0FW6uUp6NLAgMBAAGjUDBOMB0GA1UdDgQWBBQjbC09PildeLhs 23 | Pqriuy4ebIfyUzAfBgNVHSMEGDAWgBQjbC09PildeLhsPqriuy4ebIfyUzAMBgNV 24 | HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCwRJpJCgp7S+k9BT6X3kBefonE 25 | EOYtyWXBPpuyG3Qlm1rdhc66DCGForDmTxjMmHYtNmAVnM37ILW7MoflWrAkaY19 26 | gv88Fzwa5e6rWK4fTSpiEOc5WB2A3HPN9wJnhQXt1WWMDD7jJSLxLIwFqkzpDbDE 27 | 9122TtnIbmKNv0UQpzPV3Ygbqojy6eZHUOT05NaOT7vviv5QwMAH5WeRfiCys8CG 28 | Sno/o830OniEHvePTYswLlX22LyfSHeoTQCCI8pocytl7IwARKCvBgeFqvPrMiqP 29 | ch16FiU9II8KaMgpebrUSz3J1BApOOd1LBd42BeTAkNSxjRvbh8/lDWfnE7ODbKc 30 | b6Ad3V9flFb5OBZH4aTi6QfrDnBmbLgLL8o/MLM+d3Kg94XRU9LjC2rjivQ6MC53 31 | EnWNobcJFY+soXsJokGtFxKgIx8XrhF5GOsT2f1pmMlYL4cjlU0uWkPOOkhq8tIp 32 | R8cBYphzXu1v6h2AaZLRq184e30ZO98omKyQoQ2KAm5AZayRrZZtjvEZPNamSuVQ 33 | iPe3o/4tyQGq+jEMAEjLlDECu0dEa6RFntcbBPMBP3wZwE2bI9GYgvyaZd63DNdm 34 | Xd65m0mmfOWYttfrDT3Q95YP54nHpIxKBw1eFOzrnXOqbKVmJ/1FDP2yWeooKVLf 35 | KvbxUcDaVvXB0EU0bg== 36 | -----END CERTIFICATE----- 37 | -------------------------------------------------------------------------------- /pkg/mapper/entity_restapi/r2e/r2e.go: -------------------------------------------------------------------------------- 1 | package r2e 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/davecgh/go-spew/spew" 7 | "github.com/openflagr/flagr/pkg/entity" 8 | "github.com/openflagr/flagr/pkg/util" 9 | "github.com/openflagr/flagr/swagger_gen/models" 10 | ) 11 | 12 | // MapDistributions maps distribution 13 | func MapDistributions(r []*models.Distribution, segmentID uint) []entity.Distribution { 14 | e := make([]entity.Distribution, len(r)) 15 | for i, d := range r { 16 | e[i] = MapDistribution(d, segmentID) 17 | } 18 | return e 19 | } 20 | 21 | // MapDistribution maps distribution 22 | func MapDistribution(r *models.Distribution, segmentID uint) entity.Distribution { 23 | e := entity.Distribution{ 24 | SegmentID: segmentID, 25 | VariantID: uint(*r.VariantID), 26 | VariantKey: util.SafeString(r.VariantKey), 27 | Percent: uint(*r.Percent), 28 | } 29 | return e 30 | } 31 | 32 | // MapAttachment maps attachment 33 | func MapAttachment(a interface{}) (entity.Attachment, error) { 34 | e := entity.Attachment{} 35 | 36 | if a != nil { 37 | m, ok := a.(map[string]interface{}) 38 | if !ok { 39 | return e, fmt.Errorf("Make sure JSON is properly formatted into key/value pairs. Invalid attachment format %s", spew.Sdump(a)) 40 | } 41 | e = m 42 | } 43 | return e, nil 44 | } 45 | -------------------------------------------------------------------------------- /swagger/evaluation.yaml: -------------------------------------------------------------------------------- 1 | post: 2 | tags: 3 | - evaluation 4 | operationId: postEvaluation 5 | parameters: 6 | - in: body 7 | name: body 8 | description: evalution context 9 | required: true 10 | schema: 11 | $ref: "#/definitions/evalContext" 12 | responses: 13 | 200: 14 | description: evaluation result 15 | schema: 16 | $ref: "#/definitions/evalResult" 17 | default: 18 | description: generic error response 19 | schema: 20 | $ref: "#/definitions/error" 21 | -------------------------------------------------------------------------------- /swagger/evaluation_batch.yaml: -------------------------------------------------------------------------------- 1 | post: 2 | tags: 3 | - evaluation 4 | operationId: postEvaluationBatch 5 | parameters: 6 | - in: body 7 | name: body 8 | description: evalution batch request 9 | required: true 10 | schema: 11 | $ref: "#/definitions/evaluationBatchRequest" 12 | responses: 13 | 200: 14 | description: evaluation batch result 15 | schema: 16 | $ref: "#/definitions/evaluationBatchResponse" 17 | default: 18 | description: generic error response 19 | schema: 20 | $ref: "#/definitions/error" 21 | -------------------------------------------------------------------------------- /swagger/export_eval_cache_json.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - export 4 | operationId: getExportEvalCacheJSON 5 | description: Export JSON format of the eval cache dump 6 | produces: 7 | - application/json 8 | responses: 9 | 200: 10 | description: OK 11 | schema: 12 | type: object 13 | default: 14 | description: generic error response 15 | schema: 16 | $ref: "#/definitions/error" 17 | -------------------------------------------------------------------------------- /swagger/export_sqlite.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - export 4 | operationId: getExportSqlite 5 | parameters: 6 | - in: query 7 | name: exclude_snapshots 8 | type: boolean 9 | description: > 10 | export without snapshots data - useful for smaller db without snapshots 11 | description: Export sqlite3 format of the db dump, which is converted from the main database. 12 | produces: 13 | - application/octet-stream 14 | responses: 15 | 200: 16 | description: OK 17 | schema: 18 | type: file 19 | default: 20 | description: generic error response 21 | schema: 22 | $ref: "#/definitions/error" 23 | -------------------------------------------------------------------------------- /swagger/flag.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - flag 4 | operationId: getFlag 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag to get 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | responses: 14 | 200: 15 | description: returns the flag 16 | schema: 17 | $ref: "#/definitions/flag" 18 | default: 19 | description: generic error response 20 | schema: 21 | $ref: "#/definitions/error" 22 | delete: 23 | tags: 24 | - flag 25 | operationId: deleteFlag 26 | parameters: 27 | - in: path 28 | name: flagID 29 | description: numeric ID of the flag 30 | required: true 31 | type: integer 32 | format: int64 33 | minimum: 1 34 | responses: 35 | 200: 36 | description: OK deleted 37 | default: 38 | description: generic error response 39 | schema: 40 | $ref: "#/definitions/error" 41 | put: 42 | tags: 43 | - flag 44 | operationId: putFlag 45 | parameters: 46 | - in: path 47 | name: flagID 48 | description: numeric ID of the flag to get 49 | required: true 50 | type: integer 51 | format: int64 52 | minimum: 1 53 | - in: body 54 | name: body 55 | description: update a flag 56 | required: true 57 | schema: 58 | $ref: "#/definitions/putFlagRequest" 59 | responses: 60 | 200: 61 | description: returns the flag 62 | schema: 63 | $ref: "#/definitions/flag" 64 | default: 65 | description: generic error response 66 | schema: 67 | $ref: "#/definitions/error" 68 | -------------------------------------------------------------------------------- /swagger/flag_enabled.yaml: -------------------------------------------------------------------------------- 1 | put: 2 | tags: 3 | - flag 4 | operationId: setFlagEnabled 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag to get 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: body 14 | name: body 15 | description: set flag enabled state 16 | required: true 17 | schema: 18 | $ref: "#/definitions/setFlagEnabledRequest" 19 | responses: 20 | 200: 21 | description: returns the flag 22 | schema: 23 | $ref: "#/definitions/flag" 24 | default: 25 | description: generic error response 26 | schema: 27 | $ref: "#/definitions/error" 28 | -------------------------------------------------------------------------------- /swagger/flag_entity_types.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - flag 4 | operationId: getFlagEntityTypes 5 | responses: 6 | 200: 7 | description: returns all the FlagEntityTypes 8 | schema: 9 | type: array 10 | items: 11 | type: string 12 | minLength: 1 13 | default: 14 | description: generic error response 15 | schema: 16 | $ref: "#/definitions/error" 17 | -------------------------------------------------------------------------------- /swagger/flag_restore.yaml: -------------------------------------------------------------------------------- 1 | put: 2 | tags: 3 | - flag 4 | operationId: restoreFlag 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag to get 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | responses: 14 | 200: 15 | description: returns the flag 16 | schema: 17 | $ref: "#/definitions/flag" 18 | default: 19 | description: generic error response 20 | schema: 21 | $ref: "#/definitions/error" 22 | -------------------------------------------------------------------------------- /swagger/flag_segment.yaml: -------------------------------------------------------------------------------- 1 | put: 2 | tags: 3 | - segment 4 | operationId: putSegment 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: path 14 | name: segmentID 15 | description: numeric ID of the segment 16 | required: true 17 | type: integer 18 | format: int64 19 | minimum: 1 20 | - in: body 21 | name: body 22 | description: update a segment 23 | required: true 24 | schema: 25 | $ref: "#/definitions/putSegmentRequest" 26 | responses: 27 | 200: 28 | description: segment updated 29 | schema: 30 | $ref: "#/definitions/segment" 31 | default: 32 | description: generic error response 33 | schema: 34 | $ref: "#/definitions/error" 35 | delete: 36 | tags: 37 | - segment 38 | operationId: deleteSegment 39 | parameters: 40 | - in: path 41 | name: flagID 42 | description: numeric ID of the flag 43 | required: true 44 | type: integer 45 | format: int64 46 | minimum: 1 47 | - in: path 48 | name: segmentID 49 | description: numeric ID of the segment 50 | required: true 51 | type: integer 52 | format: int64 53 | minimum: 1 54 | responses: 55 | 200: 56 | description: deleted 57 | default: 58 | description: generic error response 59 | schema: 60 | $ref: "#/definitions/error" 61 | -------------------------------------------------------------------------------- /swagger/flag_segment_constraint.yaml: -------------------------------------------------------------------------------- 1 | put: 2 | tags: 3 | - constraint 4 | operationId: putConstraint 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: path 14 | name: segmentID 15 | description: numeric ID of the segment 16 | required: true 17 | type: integer 18 | format: int64 19 | minimum: 1 20 | - in: path 21 | name: constraintID 22 | description: numeric ID of the constraint 23 | required: true 24 | type: integer 25 | format: int64 26 | minimum: 1 27 | - in: body 28 | name: body 29 | description: create a constraint 30 | required: true 31 | schema: 32 | $ref: "#/definitions/createConstraintRequest" 33 | responses: 34 | 200: 35 | description: constraint just updated 36 | schema: 37 | $ref: "#/definitions/constraint" 38 | default: 39 | description: generic error response 40 | schema: 41 | $ref: "#/definitions/error" 42 | delete: 43 | tags: 44 | - constraint 45 | operationId: deleteConstraint 46 | parameters: 47 | - in: path 48 | name: flagID 49 | description: numeric ID of the flag 50 | required: true 51 | type: integer 52 | format: int64 53 | minimum: 1 54 | - in: path 55 | name: segmentID 56 | description: numeric ID of the segment 57 | required: true 58 | type: integer 59 | format: int64 60 | minimum: 1 61 | - in: path 62 | name: constraintID 63 | description: numeric ID of the constraint 64 | required: true 65 | type: integer 66 | format: int64 67 | minimum: 1 68 | responses: 69 | 200: 70 | description: deleted 71 | default: 72 | description: generic error response 73 | schema: 74 | $ref: "#/definitions/error" 75 | -------------------------------------------------------------------------------- /swagger/flag_segment_constraints.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - constraint 4 | operationId: findConstraints 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: path 14 | name: segmentID 15 | description: numeric ID of the segment 16 | required: true 17 | type: integer 18 | format: int64 19 | minimum: 1 20 | responses: 21 | 200: 22 | description: constraints under the segment 23 | schema: 24 | type: array 25 | items: 26 | $ref: "#/definitions/constraint" 27 | default: 28 | description: generic error response 29 | schema: 30 | $ref: "#/definitions/error" 31 | post: 32 | tags: 33 | - constraint 34 | operationId: createConstraint 35 | parameters: 36 | - in: path 37 | name: flagID 38 | description: numeric ID of the flag 39 | required: true 40 | type: integer 41 | format: int64 42 | minimum: 1 43 | - in: path 44 | name: segmentID 45 | description: numeric ID of the segment 46 | required: true 47 | type: integer 48 | format: int64 49 | minimum: 1 50 | - in: body 51 | name: body 52 | description: create a constraint 53 | required: true 54 | schema: 55 | $ref: "#/definitions/createConstraintRequest" 56 | responses: 57 | 200: 58 | description: the constraint created 59 | schema: 60 | $ref: "#/definitions/constraint" 61 | default: 62 | description: generic error response 63 | schema: 64 | $ref: "#/definitions/error" 65 | -------------------------------------------------------------------------------- /swagger/flag_segment_distributions.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - distribution 4 | operationId: findDistributions 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: path 14 | name: segmentID 15 | description: numeric ID of the segment 16 | required: true 17 | type: integer 18 | format: int64 19 | minimum: 1 20 | responses: 21 | 200: 22 | description: distribution under the segment 23 | schema: 24 | type: array 25 | items: 26 | $ref: "#/definitions/distribution" 27 | default: 28 | description: generic error response 29 | schema: 30 | $ref: "#/definitions/error" 31 | put: 32 | tags: 33 | - distribution 34 | operationId: putDistributions 35 | description: replace the distribution with the new setting 36 | parameters: 37 | - in: path 38 | name: flagID 39 | description: numeric ID of the flag 40 | required: true 41 | type: integer 42 | format: int64 43 | minimum: 1 44 | - in: path 45 | name: segmentID 46 | description: numeric ID of the segment 47 | required: true 48 | type: integer 49 | format: int64 50 | minimum: 1 51 | - in: body 52 | name: body 53 | description: array of distributions 54 | required: true 55 | schema: 56 | $ref: "#/definitions/putDistributionsRequest" 57 | responses: 58 | 200: 59 | description: distribution under the segment 60 | schema: 61 | type: array 62 | items: 63 | $ref: "#/definitions/distribution" 64 | default: 65 | description: generic error response 66 | schema: 67 | $ref: "#/definitions/error" 68 | -------------------------------------------------------------------------------- /swagger/flag_segments.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - segment 4 | operationId: findSegments 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag to get 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | responses: 14 | 200: 15 | description: segments ordered by rank of the flag 16 | schema: 17 | type: array 18 | items: 19 | $ref: "#/definitions/segment" 20 | default: 21 | description: generic error response 22 | schema: 23 | $ref: "#/definitions/error" 24 | post: 25 | tags: 26 | - segment 27 | operationId: createSegment 28 | parameters: 29 | - in: path 30 | name: flagID 31 | description: numeric ID of the flag to get 32 | required: true 33 | type: integer 34 | format: int64 35 | minimum: 1 36 | - in: body 37 | name: body 38 | description: create a segment under a flag 39 | required: true 40 | schema: 41 | $ref: "#/definitions/createSegmentRequest" 42 | responses: 43 | 200: 44 | description: segment created 45 | schema: 46 | $ref: "#/definitions/segment" 47 | default: 48 | description: generic error response 49 | schema: 50 | $ref: "#/definitions/error" 51 | -------------------------------------------------------------------------------- /swagger/flag_segments_reorder.yaml: -------------------------------------------------------------------------------- 1 | put: 2 | tags: 3 | - segment 4 | operationId: putSegmentsReorder 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: body 14 | name: body 15 | description: reorder segments 16 | required: true 17 | schema: 18 | $ref: "#/definitions/putSegmentReorderRequest" 19 | responses: 20 | 200: 21 | description: segments reordered 22 | default: 23 | description: generic error response 24 | schema: 25 | $ref: "#/definitions/error" 26 | -------------------------------------------------------------------------------- /swagger/flag_snapshots.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - flag 4 | operationId: getFlagSnapshots 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag to get 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: query 14 | name: limit 15 | type: integer 16 | format: int64 17 | description: the number of snapshots to return 18 | - in: query 19 | name: offset 20 | type: integer 21 | format: int64 22 | description: return snapshots given the offset, it should usually set together with limit 23 | - in: query 24 | name: sort 25 | type: string 26 | enum: 27 | - ASC 28 | - DESC 29 | description: sort order 30 | responses: 31 | 200: 32 | description: returns the flag snapshots 33 | schema: 34 | type: array 35 | items: 36 | $ref: "#/definitions/flagSnapshot" 37 | default: 38 | description: generic error response 39 | schema: 40 | $ref: "#/definitions/error" 41 | -------------------------------------------------------------------------------- /swagger/flag_tag.yaml: -------------------------------------------------------------------------------- 1 | delete: 2 | tags: 3 | - tag 4 | operationId: deleteTag 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: path 14 | name: tagID 15 | description: numeric ID of the tag 16 | required: true 17 | type: integer 18 | format: int64 19 | minimum: 1 20 | responses: 21 | 200: 22 | description: deleted 23 | default: 24 | description: generic error response 25 | schema: 26 | $ref: "#/definitions/error" 27 | -------------------------------------------------------------------------------- /swagger/flag_tags.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - tag 4 | operationId: findTags 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | responses: 14 | 200: 15 | description: tag ordered by tagID 16 | schema: 17 | type: array 18 | items: 19 | $ref: "#/definitions/tag" 20 | default: 21 | description: generic error response 22 | schema: 23 | $ref: "#/definitions/error" 24 | post: 25 | tags: 26 | - tag 27 | operationId: createTag 28 | parameters: 29 | - in: path 30 | name: flagID 31 | description: numeric ID of the flag 32 | required: true 33 | type: integer 34 | format: int64 35 | minimum: 1 36 | - in: body 37 | name: body 38 | description: create a tag 39 | required: true 40 | schema: 41 | $ref: "#/definitions/createTagRequest" 42 | responses: 43 | 200: 44 | description: tag just created 45 | schema: 46 | $ref: "#/definitions/tag" 47 | default: 48 | description: generic error response 49 | schema: 50 | $ref: "#/definitions/error" 51 | -------------------------------------------------------------------------------- /swagger/flag_variant.yaml: -------------------------------------------------------------------------------- 1 | put: 2 | tags: 3 | - variant 4 | operationId: putVariant 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | - in: path 14 | name: variantID 15 | description: numeric ID of the variant 16 | required: true 17 | type: integer 18 | format: int64 19 | minimum: 1 20 | - in: body 21 | name: body 22 | description: update a variant 23 | required: true 24 | schema: 25 | $ref: "#/definitions/putVariantRequest" 26 | responses: 27 | 200: 28 | description: variant just updated 29 | schema: 30 | $ref: "#/definitions/variant" 31 | default: 32 | description: generic error response 33 | schema: 34 | $ref: "#/definitions/error" 35 | delete: 36 | tags: 37 | - variant 38 | operationId: deleteVariant 39 | parameters: 40 | - in: path 41 | name: flagID 42 | description: numeric ID of the flag 43 | required: true 44 | type: integer 45 | format: int64 46 | minimum: 1 47 | - in: path 48 | name: variantID 49 | description: numeric ID of the variant 50 | required: true 51 | type: integer 52 | format: int64 53 | minimum: 1 54 | responses: 55 | 200: 56 | description: deleted 57 | default: 58 | description: generic error response 59 | schema: 60 | $ref: "#/definitions/error" 61 | -------------------------------------------------------------------------------- /swagger/flag_variants.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - variant 4 | operationId: findVariants 5 | parameters: 6 | - in: path 7 | name: flagID 8 | description: numeric ID of the flag 9 | required: true 10 | type: integer 11 | format: int64 12 | minimum: 1 13 | responses: 14 | 200: 15 | description: variant ordered by variantID 16 | schema: 17 | type: array 18 | items: 19 | $ref: "#/definitions/variant" 20 | default: 21 | description: generic error response 22 | schema: 23 | $ref: "#/definitions/error" 24 | post: 25 | tags: 26 | - variant 27 | operationId: createVariant 28 | parameters: 29 | - in: path 30 | name: flagID 31 | description: numeric ID of the flag 32 | required: true 33 | type: integer 34 | format: int64 35 | minimum: 1 36 | - in: body 37 | name: body 38 | description: create a variant 39 | required: true 40 | schema: 41 | $ref: "#/definitions/createVariantRequest" 42 | responses: 43 | 200: 44 | description: variant just created 45 | schema: 46 | $ref: "#/definitions/variant" 47 | default: 48 | description: generic error response 49 | schema: 50 | $ref: "#/definitions/error" 51 | -------------------------------------------------------------------------------- /swagger/flags.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - flag 4 | operationId: findFlags 5 | parameters: 6 | - in: query 7 | name: limit 8 | type: integer 9 | format: int64 10 | description: the numbers of flags to return 11 | - in: query 12 | name: enabled 13 | type: boolean 14 | description: return flags having given enabled status 15 | - in: query 16 | name: description 17 | type: string 18 | description: return flags exactly matching given description 19 | - in: query 20 | name: tags 21 | type: string 22 | description: return flags with the given tags (comma separated) 23 | - in: query 24 | name: description_like 25 | type: string 26 | description: return flags partially matching given description 27 | - in: query 28 | name: key 29 | type: string 30 | description: return flags matching given key 31 | - in: query 32 | name: offset 33 | type: integer 34 | format: int64 35 | description: return flags given the offset, it should usually set together with limit 36 | - in: query 37 | name: preload 38 | type: boolean 39 | description: return flags with preloaded segments and variants 40 | - in: query 41 | name: deleted 42 | type: boolean 43 | description: return all deleted flags 44 | responses: 45 | 200: 46 | description: list all the flags 47 | schema: 48 | type: array 49 | items: 50 | $ref: "#/definitions/flag" 51 | default: 52 | description: generic error response 53 | schema: 54 | $ref: "#/definitions/error" 55 | post: 56 | tags: 57 | - flag 58 | operationId: createFlag 59 | parameters: 60 | - in: body 61 | name: body 62 | description: create a flag 63 | required: true 64 | schema: 65 | $ref: "#/definitions/createFlagRequest" 66 | responses: 67 | 200: 68 | description: returns the created flag 69 | schema: 70 | $ref: "#/definitions/flag" 71 | default: 72 | description: generic error response 73 | schema: 74 | $ref: "#/definitions/error" 75 | -------------------------------------------------------------------------------- /swagger/health.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - health 4 | operationId: getHealth 5 | description: Check if Flagr is healthy 6 | responses: 7 | 200: 8 | description: status of health check 9 | schema: 10 | $ref: "#/definitions/health" 11 | default: 12 | description: generic error response 13 | schema: 14 | $ref: "#/definitions/error" 15 | -------------------------------------------------------------------------------- /swagger/tags.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - tag 4 | operationId: findAllTags 5 | parameters: 6 | - in: query 7 | name: limit 8 | type: integer 9 | format: int64 10 | description: the numbers of tags to return 11 | - in: query 12 | name: offset 13 | type: integer 14 | format: int64 15 | description: return tags given the offset, it should usually set together with limit 16 | - in: query 17 | name: value_like 18 | type: string 19 | description: return tags partially matching given value 20 | responses: 21 | 200: 22 | description: list all the tags 23 | schema: 24 | type: array 25 | items: 26 | $ref: "#/definitions/tag" 27 | default: 28 | description: generic error response 29 | schema: 30 | $ref: "#/definitions/error" -------------------------------------------------------------------------------- /swagger_gen/cmd/flagr-server/main.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "os" 8 | 9 | "github.com/go-openapi/loads" 10 | flags "github.com/jessevdk/go-flags" 11 | 12 | "github.com/openflagr/flagr/swagger_gen/restapi" 13 | "github.com/openflagr/flagr/swagger_gen/restapi/operations" 14 | ) 15 | 16 | // This file was generated by the swagger tool. 17 | // Make sure not to overwrite this file after you generated it because all your edits would be lost! 18 | 19 | func main() { 20 | 21 | swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON) 22 | if err != nil { 23 | log.Fatalln(err) 24 | } 25 | 26 | api := operations.NewFlagrAPI(swaggerSpec) 27 | server := restapi.NewServer(api) 28 | defer server.Shutdown() 29 | 30 | parser := flags.NewParser(server, flags.Default) 31 | parser.ShortDescription = "Flagr" 32 | parser.LongDescription = "Flagr is a feature flagging, A/B testing and dynamic configuration microservice. The base path for all the APIs is \"/api/v1\".\n" 33 | server.ConfigureFlags() 34 | for _, optsGroup := range api.CommandLineOptionsGroups { 35 | _, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options) 36 | if err != nil { 37 | log.Fatalln(err) 38 | } 39 | } 40 | 41 | if _, err := parser.Parse(); err != nil { 42 | code := 1 43 | if fe, ok := err.(*flags.Error); ok { 44 | if fe.Type == flags.ErrHelp { 45 | code = 0 46 | } 47 | } 48 | os.Exit(code) 49 | } 50 | 51 | server.ConfigureAPI() 52 | 53 | if err := server.Serve(); err != nil { 54 | log.Fatalln(err) 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /swagger_gen/models/create_flag_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // CreateFlagRequest create flag request 18 | // 19 | // swagger:model createFlagRequest 20 | type CreateFlagRequest struct { 21 | 22 | // description 23 | // Required: true 24 | // Min Length: 1 25 | Description *string `json:"description"` 26 | 27 | // unique key representation of the flag 28 | Key string `json:"key,omitempty"` 29 | 30 | // template for flag creation 31 | Template string `json:"template,omitempty"` 32 | } 33 | 34 | // Validate validates this create flag request 35 | func (m *CreateFlagRequest) Validate(formats strfmt.Registry) error { 36 | var res []error 37 | 38 | if err := m.validateDescription(formats); err != nil { 39 | res = append(res, err) 40 | } 41 | 42 | if len(res) > 0 { 43 | return errors.CompositeValidationError(res...) 44 | } 45 | return nil 46 | } 47 | 48 | func (m *CreateFlagRequest) validateDescription(formats strfmt.Registry) error { 49 | 50 | if err := validate.Required("description", "body", m.Description); err != nil { 51 | return err 52 | } 53 | 54 | if err := validate.MinLength("description", "body", *m.Description, 1); err != nil { 55 | return err 56 | } 57 | 58 | return nil 59 | } 60 | 61 | // ContextValidate validates this create flag request based on context it is used 62 | func (m *CreateFlagRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 63 | return nil 64 | } 65 | 66 | // MarshalBinary interface implementation 67 | func (m *CreateFlagRequest) MarshalBinary() ([]byte, error) { 68 | if m == nil { 69 | return nil, nil 70 | } 71 | return swag.WriteJSON(m) 72 | } 73 | 74 | // UnmarshalBinary interface implementation 75 | func (m *CreateFlagRequest) UnmarshalBinary(b []byte) error { 76 | var res CreateFlagRequest 77 | if err := swag.ReadJSON(b, &res); err != nil { 78 | return err 79 | } 80 | *m = res 81 | return nil 82 | } 83 | -------------------------------------------------------------------------------- /swagger_gen/models/create_tag_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // CreateTagRequest create tag request 18 | // 19 | // swagger:model createTagRequest 20 | type CreateTagRequest struct { 21 | 22 | // value 23 | // Required: true 24 | // Min Length: 1 25 | Value *string `json:"value"` 26 | } 27 | 28 | // Validate validates this create tag request 29 | func (m *CreateTagRequest) Validate(formats strfmt.Registry) error { 30 | var res []error 31 | 32 | if err := m.validateValue(formats); err != nil { 33 | res = append(res, err) 34 | } 35 | 36 | if len(res) > 0 { 37 | return errors.CompositeValidationError(res...) 38 | } 39 | return nil 40 | } 41 | 42 | func (m *CreateTagRequest) validateValue(formats strfmt.Registry) error { 43 | 44 | if err := validate.Required("value", "body", m.Value); err != nil { 45 | return err 46 | } 47 | 48 | if err := validate.MinLength("value", "body", *m.Value, 1); err != nil { 49 | return err 50 | } 51 | 52 | return nil 53 | } 54 | 55 | // ContextValidate validates this create tag request based on context it is used 56 | func (m *CreateTagRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 57 | return nil 58 | } 59 | 60 | // MarshalBinary interface implementation 61 | func (m *CreateTagRequest) MarshalBinary() ([]byte, error) { 62 | if m == nil { 63 | return nil, nil 64 | } 65 | return swag.WriteJSON(m) 66 | } 67 | 68 | // UnmarshalBinary interface implementation 69 | func (m *CreateTagRequest) UnmarshalBinary(b []byte) error { 70 | var res CreateTagRequest 71 | if err := swag.ReadJSON(b, &res); err != nil { 72 | return err 73 | } 74 | *m = res 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /swagger_gen/models/create_variant_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // CreateVariantRequest create variant request 18 | // 19 | // swagger:model createVariantRequest 20 | type CreateVariantRequest struct { 21 | 22 | // attachment 23 | Attachment interface{} `json:"attachment,omitempty"` 24 | 25 | // key 26 | // Required: true 27 | // Min Length: 1 28 | Key *string `json:"key"` 29 | } 30 | 31 | // Validate validates this create variant request 32 | func (m *CreateVariantRequest) Validate(formats strfmt.Registry) error { 33 | var res []error 34 | 35 | if err := m.validateKey(formats); err != nil { 36 | res = append(res, err) 37 | } 38 | 39 | if len(res) > 0 { 40 | return errors.CompositeValidationError(res...) 41 | } 42 | return nil 43 | } 44 | 45 | func (m *CreateVariantRequest) validateKey(formats strfmt.Registry) error { 46 | 47 | if err := validate.Required("key", "body", m.Key); err != nil { 48 | return err 49 | } 50 | 51 | if err := validate.MinLength("key", "body", *m.Key, 1); err != nil { 52 | return err 53 | } 54 | 55 | return nil 56 | } 57 | 58 | // ContextValidate validates this create variant request based on context it is used 59 | func (m *CreateVariantRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 60 | return nil 61 | } 62 | 63 | // MarshalBinary interface implementation 64 | func (m *CreateVariantRequest) MarshalBinary() ([]byte, error) { 65 | if m == nil { 66 | return nil, nil 67 | } 68 | return swag.WriteJSON(m) 69 | } 70 | 71 | // UnmarshalBinary interface implementation 72 | func (m *CreateVariantRequest) UnmarshalBinary(b []byte) error { 73 | var res CreateVariantRequest 74 | if err := swag.ReadJSON(b, &res); err != nil { 75 | return err 76 | } 77 | *m = res 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /swagger_gen/models/error.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // Error error 18 | // 19 | // swagger:model error 20 | type Error struct { 21 | 22 | // message 23 | // Required: true 24 | // Min Length: 1 25 | Message *string `json:"message"` 26 | } 27 | 28 | // Validate validates this error 29 | func (m *Error) Validate(formats strfmt.Registry) error { 30 | var res []error 31 | 32 | if err := m.validateMessage(formats); err != nil { 33 | res = append(res, err) 34 | } 35 | 36 | if len(res) > 0 { 37 | return errors.CompositeValidationError(res...) 38 | } 39 | return nil 40 | } 41 | 42 | func (m *Error) validateMessage(formats strfmt.Registry) error { 43 | 44 | if err := validate.Required("message", "body", m.Message); err != nil { 45 | return err 46 | } 47 | 48 | if err := validate.MinLength("message", "body", *m.Message, 1); err != nil { 49 | return err 50 | } 51 | 52 | return nil 53 | } 54 | 55 | // ContextValidate validates this error based on context it is used 56 | func (m *Error) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 57 | return nil 58 | } 59 | 60 | // MarshalBinary interface implementation 61 | func (m *Error) MarshalBinary() ([]byte, error) { 62 | if m == nil { 63 | return nil, nil 64 | } 65 | return swag.WriteJSON(m) 66 | } 67 | 68 | // UnmarshalBinary interface implementation 69 | func (m *Error) UnmarshalBinary(b []byte) error { 70 | var res Error 71 | if err := swag.ReadJSON(b, &res); err != nil { 72 | return err 73 | } 74 | *m = res 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /swagger_gen/models/evaluation_entity.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/strfmt" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // EvaluationEntity evaluation entity 16 | // 17 | // swagger:model evaluationEntity 18 | type EvaluationEntity struct { 19 | 20 | // entity context 21 | EntityContext interface{} `json:"entityContext,omitempty"` 22 | 23 | // entity ID 24 | EntityID string `json:"entityID,omitempty"` 25 | 26 | // entity type 27 | EntityType string `json:"entityType,omitempty"` 28 | } 29 | 30 | // Validate validates this evaluation entity 31 | func (m *EvaluationEntity) Validate(formats strfmt.Registry) error { 32 | return nil 33 | } 34 | 35 | // ContextValidate validates this evaluation entity based on context it is used 36 | func (m *EvaluationEntity) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 37 | return nil 38 | } 39 | 40 | // MarshalBinary interface implementation 41 | func (m *EvaluationEntity) MarshalBinary() ([]byte, error) { 42 | if m == nil { 43 | return nil, nil 44 | } 45 | return swag.WriteJSON(m) 46 | } 47 | 48 | // UnmarshalBinary interface implementation 49 | func (m *EvaluationEntity) UnmarshalBinary(b []byte) error { 50 | var res EvaluationEntity 51 | if err := swag.ReadJSON(b, &res); err != nil { 52 | return err 53 | } 54 | *m = res 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/models/health.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/strfmt" 12 | "github.com/go-openapi/swag" 13 | ) 14 | 15 | // Health health 16 | // 17 | // swagger:model health 18 | type Health struct { 19 | 20 | // status 21 | Status string `json:"status,omitempty"` 22 | } 23 | 24 | // Validate validates this health 25 | func (m *Health) Validate(formats strfmt.Registry) error { 26 | return nil 27 | } 28 | 29 | // ContextValidate validates this health based on context it is used 30 | func (m *Health) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 31 | return nil 32 | } 33 | 34 | // MarshalBinary interface implementation 35 | func (m *Health) MarshalBinary() ([]byte, error) { 36 | if m == nil { 37 | return nil, nil 38 | } 39 | return swag.WriteJSON(m) 40 | } 41 | 42 | // UnmarshalBinary interface implementation 43 | func (m *Health) UnmarshalBinary(b []byte) error { 44 | var res Health 45 | if err := swag.ReadJSON(b, &res); err != nil { 46 | return err 47 | } 48 | *m = res 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /swagger_gen/models/put_flag_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // PutFlagRequest put flag request 18 | // 19 | // swagger:model putFlagRequest 20 | type PutFlagRequest struct { 21 | 22 | // enabled data records will get data logging in the metrics pipeline, for example, kafka. 23 | DataRecordsEnabled *bool `json:"dataRecordsEnabled,omitempty"` 24 | 25 | // description 26 | // Min Length: 1 27 | Description *string `json:"description,omitempty"` 28 | 29 | // enabled 30 | Enabled *bool `json:"enabled,omitempty"` 31 | 32 | // it will overwrite entityType into evaluation logs if it's not empty 33 | EntityType *string `json:"entityType,omitempty"` 34 | 35 | // key 36 | Key *string `json:"key,omitempty"` 37 | 38 | // notes 39 | Notes *string `json:"notes,omitempty"` 40 | } 41 | 42 | // Validate validates this put flag request 43 | func (m *PutFlagRequest) Validate(formats strfmt.Registry) error { 44 | var res []error 45 | 46 | if err := m.validateDescription(formats); err != nil { 47 | res = append(res, err) 48 | } 49 | 50 | if len(res) > 0 { 51 | return errors.CompositeValidationError(res...) 52 | } 53 | return nil 54 | } 55 | 56 | func (m *PutFlagRequest) validateDescription(formats strfmt.Registry) error { 57 | if swag.IsZero(m.Description) { // not required 58 | return nil 59 | } 60 | 61 | if err := validate.MinLength("description", "body", *m.Description, 1); err != nil { 62 | return err 63 | } 64 | 65 | return nil 66 | } 67 | 68 | // ContextValidate validates this put flag request based on context it is used 69 | func (m *PutFlagRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 70 | return nil 71 | } 72 | 73 | // MarshalBinary interface implementation 74 | func (m *PutFlagRequest) MarshalBinary() ([]byte, error) { 75 | if m == nil { 76 | return nil, nil 77 | } 78 | return swag.WriteJSON(m) 79 | } 80 | 81 | // UnmarshalBinary interface implementation 82 | func (m *PutFlagRequest) UnmarshalBinary(b []byte) error { 83 | var res PutFlagRequest 84 | if err := swag.ReadJSON(b, &res); err != nil { 85 | return err 86 | } 87 | *m = res 88 | return nil 89 | } 90 | -------------------------------------------------------------------------------- /swagger_gen/models/put_segment_reorder_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | "strconv" 11 | 12 | "github.com/go-openapi/errors" 13 | "github.com/go-openapi/strfmt" 14 | "github.com/go-openapi/swag" 15 | "github.com/go-openapi/validate" 16 | ) 17 | 18 | // PutSegmentReorderRequest put segment reorder request 19 | // 20 | // swagger:model putSegmentReorderRequest 21 | type PutSegmentReorderRequest struct { 22 | 23 | // segment i ds 24 | // Required: true 25 | // Min Items: 1 26 | SegmentIDs []int64 `json:"segmentIDs"` 27 | } 28 | 29 | // Validate validates this put segment reorder request 30 | func (m *PutSegmentReorderRequest) Validate(formats strfmt.Registry) error { 31 | var res []error 32 | 33 | if err := m.validateSegmentIDs(formats); err != nil { 34 | res = append(res, err) 35 | } 36 | 37 | if len(res) > 0 { 38 | return errors.CompositeValidationError(res...) 39 | } 40 | return nil 41 | } 42 | 43 | func (m *PutSegmentReorderRequest) validateSegmentIDs(formats strfmt.Registry) error { 44 | 45 | if err := validate.Required("segmentIDs", "body", m.SegmentIDs); err != nil { 46 | return err 47 | } 48 | 49 | iSegmentIDsSize := int64(len(m.SegmentIDs)) 50 | 51 | if err := validate.MinItems("segmentIDs", "body", iSegmentIDsSize, 1); err != nil { 52 | return err 53 | } 54 | 55 | for i := 0; i < len(m.SegmentIDs); i++ { 56 | 57 | if err := validate.MinimumInt("segmentIDs"+"."+strconv.Itoa(i), "body", m.SegmentIDs[i], 1, false); err != nil { 58 | return err 59 | } 60 | 61 | } 62 | 63 | return nil 64 | } 65 | 66 | // ContextValidate validates this put segment reorder request based on context it is used 67 | func (m *PutSegmentReorderRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 68 | return nil 69 | } 70 | 71 | // MarshalBinary interface implementation 72 | func (m *PutSegmentReorderRequest) MarshalBinary() ([]byte, error) { 73 | if m == nil { 74 | return nil, nil 75 | } 76 | return swag.WriteJSON(m) 77 | } 78 | 79 | // UnmarshalBinary interface implementation 80 | func (m *PutSegmentReorderRequest) UnmarshalBinary(b []byte) error { 81 | var res PutSegmentReorderRequest 82 | if err := swag.ReadJSON(b, &res); err != nil { 83 | return err 84 | } 85 | *m = res 86 | return nil 87 | } 88 | -------------------------------------------------------------------------------- /swagger_gen/models/put_variant_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // PutVariantRequest put variant request 18 | // 19 | // swagger:model putVariantRequest 20 | type PutVariantRequest struct { 21 | 22 | // attachment 23 | Attachment interface{} `json:"attachment,omitempty"` 24 | 25 | // key 26 | // Required: true 27 | // Min Length: 1 28 | Key *string `json:"key"` 29 | } 30 | 31 | // Validate validates this put variant request 32 | func (m *PutVariantRequest) Validate(formats strfmt.Registry) error { 33 | var res []error 34 | 35 | if err := m.validateKey(formats); err != nil { 36 | res = append(res, err) 37 | } 38 | 39 | if len(res) > 0 { 40 | return errors.CompositeValidationError(res...) 41 | } 42 | return nil 43 | } 44 | 45 | func (m *PutVariantRequest) validateKey(formats strfmt.Registry) error { 46 | 47 | if err := validate.Required("key", "body", m.Key); err != nil { 48 | return err 49 | } 50 | 51 | if err := validate.MinLength("key", "body", *m.Key, 1); err != nil { 52 | return err 53 | } 54 | 55 | return nil 56 | } 57 | 58 | // ContextValidate validates this put variant request based on context it is used 59 | func (m *PutVariantRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 60 | return nil 61 | } 62 | 63 | // MarshalBinary interface implementation 64 | func (m *PutVariantRequest) MarshalBinary() ([]byte, error) { 65 | if m == nil { 66 | return nil, nil 67 | } 68 | return swag.WriteJSON(m) 69 | } 70 | 71 | // UnmarshalBinary interface implementation 72 | func (m *PutVariantRequest) UnmarshalBinary(b []byte) error { 73 | var res PutVariantRequest 74 | if err := swag.ReadJSON(b, &res); err != nil { 75 | return err 76 | } 77 | *m = res 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /swagger_gen/models/segment_debug_log.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // SegmentDebugLog segment debug log 18 | // 19 | // swagger:model segmentDebugLog 20 | type SegmentDebugLog struct { 21 | 22 | // msg 23 | Msg string `json:"msg,omitempty"` 24 | 25 | // segment ID 26 | // Minimum: 1 27 | SegmentID int64 `json:"segmentID,omitempty"` 28 | } 29 | 30 | // Validate validates this segment debug log 31 | func (m *SegmentDebugLog) Validate(formats strfmt.Registry) error { 32 | var res []error 33 | 34 | if err := m.validateSegmentID(formats); err != nil { 35 | res = append(res, err) 36 | } 37 | 38 | if len(res) > 0 { 39 | return errors.CompositeValidationError(res...) 40 | } 41 | return nil 42 | } 43 | 44 | func (m *SegmentDebugLog) validateSegmentID(formats strfmt.Registry) error { 45 | if swag.IsZero(m.SegmentID) { // not required 46 | return nil 47 | } 48 | 49 | if err := validate.MinimumInt("segmentID", "body", m.SegmentID, 1, false); err != nil { 50 | return err 51 | } 52 | 53 | return nil 54 | } 55 | 56 | // ContextValidate validates this segment debug log based on context it is used 57 | func (m *SegmentDebugLog) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 58 | return nil 59 | } 60 | 61 | // MarshalBinary interface implementation 62 | func (m *SegmentDebugLog) MarshalBinary() ([]byte, error) { 63 | if m == nil { 64 | return nil, nil 65 | } 66 | return swag.WriteJSON(m) 67 | } 68 | 69 | // UnmarshalBinary interface implementation 70 | func (m *SegmentDebugLog) UnmarshalBinary(b []byte) error { 71 | var res SegmentDebugLog 72 | if err := swag.ReadJSON(b, &res); err != nil { 73 | return err 74 | } 75 | *m = res 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /swagger_gen/models/set_flag_enabled_request.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package models 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "context" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/swag" 14 | "github.com/go-openapi/validate" 15 | ) 16 | 17 | // SetFlagEnabledRequest set flag enabled request 18 | // 19 | // swagger:model setFlagEnabledRequest 20 | type SetFlagEnabledRequest struct { 21 | 22 | // enabled 23 | // Required: true 24 | Enabled *bool `json:"enabled"` 25 | } 26 | 27 | // Validate validates this set flag enabled request 28 | func (m *SetFlagEnabledRequest) Validate(formats strfmt.Registry) error { 29 | var res []error 30 | 31 | if err := m.validateEnabled(formats); err != nil { 32 | res = append(res, err) 33 | } 34 | 35 | if len(res) > 0 { 36 | return errors.CompositeValidationError(res...) 37 | } 38 | return nil 39 | } 40 | 41 | func (m *SetFlagEnabledRequest) validateEnabled(formats strfmt.Registry) error { 42 | 43 | if err := validate.Required("enabled", "body", m.Enabled); err != nil { 44 | return err 45 | } 46 | 47 | return nil 48 | } 49 | 50 | // ContextValidate validates this set flag enabled request based on context it is used 51 | func (m *SetFlagEnabledRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { 52 | return nil 53 | } 54 | 55 | // MarshalBinary interface implementation 56 | func (m *SetFlagEnabledRequest) MarshalBinary() ([]byte, error) { 57 | if m == nil { 58 | return nil, nil 59 | } 60 | return swag.WriteJSON(m) 61 | } 62 | 63 | // UnmarshalBinary interface implementation 64 | func (m *SetFlagEnabledRequest) UnmarshalBinary(b []byte) error { 65 | var res SetFlagEnabledRequest 66 | if err := swag.ReadJSON(b, &res); err != nil { 67 | return err 68 | } 69 | *m = res 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /swagger_gen/restapi/doc.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | // Package restapi Flagr 4 | // 5 | // Flagr is a feature flagging, A/B testing and dynamic configuration microservice. The base path for all the APIs is "/api/v1". 6 | // 7 | // Schemes: 8 | // http 9 | // Host: localhost 10 | // BasePath: /api/v1 11 | // Version: 1.1.18 12 | // 13 | // Consumes: 14 | // - application/json 15 | // 16 | // Produces: 17 | // - application/octet-stream 18 | // - application/json 19 | // 20 | // swagger:meta 21 | package restapi 22 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/constraint/create_constraint.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package constraint 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // CreateConstraintHandlerFunc turns a function with the right signature into a create constraint handler 15 | type CreateConstraintHandlerFunc func(CreateConstraintParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn CreateConstraintHandlerFunc) Handle(params CreateConstraintParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // CreateConstraintHandler interface for that can handle valid create constraint params 23 | type CreateConstraintHandler interface { 24 | Handle(CreateConstraintParams) middleware.Responder 25 | } 26 | 27 | // NewCreateConstraint creates a new http.Handler for the create constraint operation 28 | func NewCreateConstraint(ctx *middleware.Context, handler CreateConstraintHandler) *CreateConstraint { 29 | return &CreateConstraint{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | CreateConstraint swagger:route POST /flags/{flagID}/segments/{segmentID}/constraints constraint createConstraint 34 | 35 | CreateConstraint create constraint API 36 | */ 37 | type CreateConstraint struct { 38 | Context *middleware.Context 39 | Handler CreateConstraintHandler 40 | } 41 | 42 | func (o *CreateConstraint) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewCreateConstraintParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/constraint/delete_constraint.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package constraint 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // DeleteConstraintHandlerFunc turns a function with the right signature into a delete constraint handler 15 | type DeleteConstraintHandlerFunc func(DeleteConstraintParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn DeleteConstraintHandlerFunc) Handle(params DeleteConstraintParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // DeleteConstraintHandler interface for that can handle valid delete constraint params 23 | type DeleteConstraintHandler interface { 24 | Handle(DeleteConstraintParams) middleware.Responder 25 | } 26 | 27 | // NewDeleteConstraint creates a new http.Handler for the delete constraint operation 28 | func NewDeleteConstraint(ctx *middleware.Context, handler DeleteConstraintHandler) *DeleteConstraint { 29 | return &DeleteConstraint{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | DeleteConstraint swagger:route DELETE /flags/{flagID}/segments/{segmentID}/constraints/{constraintID} constraint deleteConstraint 34 | 35 | DeleteConstraint delete constraint API 36 | */ 37 | type DeleteConstraint struct { 38 | Context *middleware.Context 39 | Handler DeleteConstraintHandler 40 | } 41 | 42 | func (o *DeleteConstraint) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewDeleteConstraintParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/constraint/find_constraints.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package constraint 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindConstraintsHandlerFunc turns a function with the right signature into a find constraints handler 15 | type FindConstraintsHandlerFunc func(FindConstraintsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindConstraintsHandlerFunc) Handle(params FindConstraintsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindConstraintsHandler interface for that can handle valid find constraints params 23 | type FindConstraintsHandler interface { 24 | Handle(FindConstraintsParams) middleware.Responder 25 | } 26 | 27 | // NewFindConstraints creates a new http.Handler for the find constraints operation 28 | func NewFindConstraints(ctx *middleware.Context, handler FindConstraintsHandler) *FindConstraints { 29 | return &FindConstraints{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindConstraints swagger:route GET /flags/{flagID}/segments/{segmentID}/constraints constraint findConstraints 34 | 35 | FindConstraints find constraints API 36 | */ 37 | type FindConstraints struct { 38 | Context *middleware.Context 39 | Handler FindConstraintsHandler 40 | } 41 | 42 | func (o *FindConstraints) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindConstraintsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/constraint/put_constraint.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package constraint 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PutConstraintHandlerFunc turns a function with the right signature into a put constraint handler 15 | type PutConstraintHandlerFunc func(PutConstraintParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PutConstraintHandlerFunc) Handle(params PutConstraintParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PutConstraintHandler interface for that can handle valid put constraint params 23 | type PutConstraintHandler interface { 24 | Handle(PutConstraintParams) middleware.Responder 25 | } 26 | 27 | // NewPutConstraint creates a new http.Handler for the put constraint operation 28 | func NewPutConstraint(ctx *middleware.Context, handler PutConstraintHandler) *PutConstraint { 29 | return &PutConstraint{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PutConstraint swagger:route PUT /flags/{flagID}/segments/{segmentID}/constraints/{constraintID} constraint putConstraint 34 | 35 | PutConstraint put constraint API 36 | */ 37 | type PutConstraint struct { 38 | Context *middleware.Context 39 | Handler PutConstraintHandler 40 | } 41 | 42 | func (o *PutConstraint) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPutConstraintParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/distribution/find_distributions.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package distribution 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindDistributionsHandlerFunc turns a function with the right signature into a find distributions handler 15 | type FindDistributionsHandlerFunc func(FindDistributionsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindDistributionsHandlerFunc) Handle(params FindDistributionsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindDistributionsHandler interface for that can handle valid find distributions params 23 | type FindDistributionsHandler interface { 24 | Handle(FindDistributionsParams) middleware.Responder 25 | } 26 | 27 | // NewFindDistributions creates a new http.Handler for the find distributions operation 28 | func NewFindDistributions(ctx *middleware.Context, handler FindDistributionsHandler) *FindDistributions { 29 | return &FindDistributions{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindDistributions swagger:route GET /flags/{flagID}/segments/{segmentID}/distributions distribution findDistributions 34 | 35 | FindDistributions find distributions API 36 | */ 37 | type FindDistributions struct { 38 | Context *middleware.Context 39 | Handler FindDistributionsHandler 40 | } 41 | 42 | func (o *FindDistributions) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindDistributionsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/distribution/put_distributions.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package distribution 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PutDistributionsHandlerFunc turns a function with the right signature into a put distributions handler 15 | type PutDistributionsHandlerFunc func(PutDistributionsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PutDistributionsHandlerFunc) Handle(params PutDistributionsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PutDistributionsHandler interface for that can handle valid put distributions params 23 | type PutDistributionsHandler interface { 24 | Handle(PutDistributionsParams) middleware.Responder 25 | } 26 | 27 | // NewPutDistributions creates a new http.Handler for the put distributions operation 28 | func NewPutDistributions(ctx *middleware.Context, handler PutDistributionsHandler) *PutDistributions { 29 | return &PutDistributions{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PutDistributions swagger:route PUT /flags/{flagID}/segments/{segmentID}/distributions distribution putDistributions 34 | 35 | replace the distribution with the new setting 36 | */ 37 | type PutDistributions struct { 38 | Context *middleware.Context 39 | Handler PutDistributionsHandler 40 | } 41 | 42 | func (o *PutDistributions) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPutDistributionsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/evaluation/post_evaluation.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package evaluation 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PostEvaluationHandlerFunc turns a function with the right signature into a post evaluation handler 15 | type PostEvaluationHandlerFunc func(PostEvaluationParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PostEvaluationHandlerFunc) Handle(params PostEvaluationParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PostEvaluationHandler interface for that can handle valid post evaluation params 23 | type PostEvaluationHandler interface { 24 | Handle(PostEvaluationParams) middleware.Responder 25 | } 26 | 27 | // NewPostEvaluation creates a new http.Handler for the post evaluation operation 28 | func NewPostEvaluation(ctx *middleware.Context, handler PostEvaluationHandler) *PostEvaluation { 29 | return &PostEvaluation{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PostEvaluation swagger:route POST /evaluation evaluation postEvaluation 34 | 35 | PostEvaluation post evaluation API 36 | */ 37 | type PostEvaluation struct { 38 | Context *middleware.Context 39 | Handler PostEvaluationHandler 40 | } 41 | 42 | func (o *PostEvaluation) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPostEvaluationParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/evaluation/post_evaluation_batch.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package evaluation 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PostEvaluationBatchHandlerFunc turns a function with the right signature into a post evaluation batch handler 15 | type PostEvaluationBatchHandlerFunc func(PostEvaluationBatchParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PostEvaluationBatchHandlerFunc) Handle(params PostEvaluationBatchParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PostEvaluationBatchHandler interface for that can handle valid post evaluation batch params 23 | type PostEvaluationBatchHandler interface { 24 | Handle(PostEvaluationBatchParams) middleware.Responder 25 | } 26 | 27 | // NewPostEvaluationBatch creates a new http.Handler for the post evaluation batch operation 28 | func NewPostEvaluationBatch(ctx *middleware.Context, handler PostEvaluationBatchHandler) *PostEvaluationBatch { 29 | return &PostEvaluationBatch{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PostEvaluationBatch swagger:route POST /evaluation/batch evaluation postEvaluationBatch 34 | 35 | PostEvaluationBatch post evaluation batch API 36 | */ 37 | type PostEvaluationBatch struct { 38 | Context *middleware.Context 39 | Handler PostEvaluationBatchHandler 40 | } 41 | 42 | func (o *PostEvaluationBatch) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPostEvaluationBatchParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/evaluation/post_evaluation_batch_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package evaluation 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "io" 10 | "net/http" 11 | 12 | "github.com/go-openapi/errors" 13 | "github.com/go-openapi/runtime" 14 | "github.com/go-openapi/runtime/middleware" 15 | "github.com/go-openapi/validate" 16 | 17 | "github.com/openflagr/flagr/swagger_gen/models" 18 | ) 19 | 20 | // NewPostEvaluationBatchParams creates a new PostEvaluationBatchParams object 21 | // 22 | // There are no default values defined in the spec. 23 | func NewPostEvaluationBatchParams() PostEvaluationBatchParams { 24 | 25 | return PostEvaluationBatchParams{} 26 | } 27 | 28 | // PostEvaluationBatchParams contains all the bound params for the post evaluation batch operation 29 | // typically these are obtained from a http.Request 30 | // 31 | // swagger:parameters postEvaluationBatch 32 | type PostEvaluationBatchParams struct { 33 | 34 | // HTTP Request Object 35 | HTTPRequest *http.Request `json:"-"` 36 | 37 | /*evalution batch request 38 | Required: true 39 | In: body 40 | */ 41 | Body *models.EvaluationBatchRequest 42 | } 43 | 44 | // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface 45 | // for simple values it will use straight method calls. 46 | // 47 | // To ensure default values, the struct must have been initialized with NewPostEvaluationBatchParams() beforehand. 48 | func (o *PostEvaluationBatchParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { 49 | var res []error 50 | 51 | o.HTTPRequest = r 52 | 53 | if runtime.HasBody(r) { 54 | defer r.Body.Close() 55 | var body models.EvaluationBatchRequest 56 | if err := route.Consumer.Consume(r.Body, &body); err != nil { 57 | if err == io.EOF { 58 | res = append(res, errors.Required("body", "body", "")) 59 | } else { 60 | res = append(res, errors.NewParseError("body", "body", "", err)) 61 | } 62 | } else { 63 | // validate body object 64 | if err := body.Validate(route.Formats); err != nil { 65 | res = append(res, err) 66 | } 67 | 68 | ctx := validate.WithOperationRequest(r.Context()) 69 | if err := body.ContextValidate(ctx, route.Formats); err != nil { 70 | res = append(res, err) 71 | } 72 | 73 | if len(res) == 0 { 74 | o.Body = &body 75 | } 76 | } 77 | } else { 78 | res = append(res, errors.Required("body", "body", "")) 79 | } 80 | if len(res) > 0 { 81 | return errors.CompositeValidationError(res...) 82 | } 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/evaluation/post_evaluation_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package evaluation 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "io" 10 | "net/http" 11 | 12 | "github.com/go-openapi/errors" 13 | "github.com/go-openapi/runtime" 14 | "github.com/go-openapi/runtime/middleware" 15 | "github.com/go-openapi/validate" 16 | 17 | "github.com/openflagr/flagr/swagger_gen/models" 18 | ) 19 | 20 | // NewPostEvaluationParams creates a new PostEvaluationParams object 21 | // 22 | // There are no default values defined in the spec. 23 | func NewPostEvaluationParams() PostEvaluationParams { 24 | 25 | return PostEvaluationParams{} 26 | } 27 | 28 | // PostEvaluationParams contains all the bound params for the post evaluation operation 29 | // typically these are obtained from a http.Request 30 | // 31 | // swagger:parameters postEvaluation 32 | type PostEvaluationParams struct { 33 | 34 | // HTTP Request Object 35 | HTTPRequest *http.Request `json:"-"` 36 | 37 | /*evalution context 38 | Required: true 39 | In: body 40 | */ 41 | Body *models.EvalContext 42 | } 43 | 44 | // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface 45 | // for simple values it will use straight method calls. 46 | // 47 | // To ensure default values, the struct must have been initialized with NewPostEvaluationParams() beforehand. 48 | func (o *PostEvaluationParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { 49 | var res []error 50 | 51 | o.HTTPRequest = r 52 | 53 | if runtime.HasBody(r) { 54 | defer r.Body.Close() 55 | var body models.EvalContext 56 | if err := route.Consumer.Consume(r.Body, &body); err != nil { 57 | if err == io.EOF { 58 | res = append(res, errors.Required("body", "body", "")) 59 | } else { 60 | res = append(res, errors.NewParseError("body", "body", "", err)) 61 | } 62 | } else { 63 | // validate body object 64 | if err := body.Validate(route.Formats); err != nil { 65 | res = append(res, err) 66 | } 67 | 68 | ctx := validate.WithOperationRequest(r.Context()) 69 | if err := body.ContextValidate(ctx, route.Formats); err != nil { 70 | res = append(res, err) 71 | } 72 | 73 | if len(res) == 0 { 74 | o.Body = &body 75 | } 76 | } 77 | } else { 78 | res = append(res, errors.Required("body", "body", "")) 79 | } 80 | if len(res) > 0 { 81 | return errors.CompositeValidationError(res...) 82 | } 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/export/get_export_eval_cache_json.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package export 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // GetExportEvalCacheJSONHandlerFunc turns a function with the right signature into a get export eval cache JSON handler 15 | type GetExportEvalCacheJSONHandlerFunc func(GetExportEvalCacheJSONParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn GetExportEvalCacheJSONHandlerFunc) Handle(params GetExportEvalCacheJSONParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // GetExportEvalCacheJSONHandler interface for that can handle valid get export eval cache JSON params 23 | type GetExportEvalCacheJSONHandler interface { 24 | Handle(GetExportEvalCacheJSONParams) middleware.Responder 25 | } 26 | 27 | // NewGetExportEvalCacheJSON creates a new http.Handler for the get export eval cache JSON operation 28 | func NewGetExportEvalCacheJSON(ctx *middleware.Context, handler GetExportEvalCacheJSONHandler) *GetExportEvalCacheJSON { 29 | return &GetExportEvalCacheJSON{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | GetExportEvalCacheJSON swagger:route GET /export/eval_cache/json export getExportEvalCacheJson 34 | 35 | Export JSON format of the eval cache dump 36 | */ 37 | type GetExportEvalCacheJSON struct { 38 | Context *middleware.Context 39 | Handler GetExportEvalCacheJSONHandler 40 | } 41 | 42 | func (o *GetExportEvalCacheJSON) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewGetExportEvalCacheJSONParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/export/get_export_eval_cache_json_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package export 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/runtime/middleware" 13 | ) 14 | 15 | // NewGetExportEvalCacheJSONParams creates a new GetExportEvalCacheJSONParams object 16 | // 17 | // There are no default values defined in the spec. 18 | func NewGetExportEvalCacheJSONParams() GetExportEvalCacheJSONParams { 19 | 20 | return GetExportEvalCacheJSONParams{} 21 | } 22 | 23 | // GetExportEvalCacheJSONParams contains all the bound params for the get export eval cache JSON operation 24 | // typically these are obtained from a http.Request 25 | // 26 | // swagger:parameters getExportEvalCacheJSON 27 | type GetExportEvalCacheJSONParams struct { 28 | 29 | // HTTP Request Object 30 | HTTPRequest *http.Request `json:"-"` 31 | } 32 | 33 | // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface 34 | // for simple values it will use straight method calls. 35 | // 36 | // To ensure default values, the struct must have been initialized with NewGetExportEvalCacheJSONParams() beforehand. 37 | func (o *GetExportEvalCacheJSONParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { 38 | var res []error 39 | 40 | o.HTTPRequest = r 41 | 42 | if len(res) > 0 { 43 | return errors.CompositeValidationError(res...) 44 | } 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/export/get_export_sqlite.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package export 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // GetExportSqliteHandlerFunc turns a function with the right signature into a get export sqlite handler 15 | type GetExportSqliteHandlerFunc func(GetExportSqliteParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn GetExportSqliteHandlerFunc) Handle(params GetExportSqliteParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // GetExportSqliteHandler interface for that can handle valid get export sqlite params 23 | type GetExportSqliteHandler interface { 24 | Handle(GetExportSqliteParams) middleware.Responder 25 | } 26 | 27 | // NewGetExportSqlite creates a new http.Handler for the get export sqlite operation 28 | func NewGetExportSqlite(ctx *middleware.Context, handler GetExportSqliteHandler) *GetExportSqlite { 29 | return &GetExportSqlite{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | GetExportSqlite swagger:route GET /export/sqlite export getExportSqlite 34 | 35 | Export sqlite3 format of the db dump, which is converted from the main database. 36 | */ 37 | type GetExportSqlite struct { 38 | Context *middleware.Context 39 | Handler GetExportSqliteHandler 40 | } 41 | 42 | func (o *GetExportSqlite) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewGetExportSqliteParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/create_flag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // CreateFlagHandlerFunc turns a function with the right signature into a create flag handler 15 | type CreateFlagHandlerFunc func(CreateFlagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn CreateFlagHandlerFunc) Handle(params CreateFlagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // CreateFlagHandler interface for that can handle valid create flag params 23 | type CreateFlagHandler interface { 24 | Handle(CreateFlagParams) middleware.Responder 25 | } 26 | 27 | // NewCreateFlag creates a new http.Handler for the create flag operation 28 | func NewCreateFlag(ctx *middleware.Context, handler CreateFlagHandler) *CreateFlag { 29 | return &CreateFlag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | CreateFlag swagger:route POST /flags flag createFlag 34 | 35 | CreateFlag create flag API 36 | */ 37 | type CreateFlag struct { 38 | Context *middleware.Context 39 | Handler CreateFlagHandler 40 | } 41 | 42 | func (o *CreateFlag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewCreateFlagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/create_flag_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "io" 10 | "net/http" 11 | 12 | "github.com/go-openapi/errors" 13 | "github.com/go-openapi/runtime" 14 | "github.com/go-openapi/runtime/middleware" 15 | "github.com/go-openapi/validate" 16 | 17 | "github.com/openflagr/flagr/swagger_gen/models" 18 | ) 19 | 20 | // NewCreateFlagParams creates a new CreateFlagParams object 21 | // 22 | // There are no default values defined in the spec. 23 | func NewCreateFlagParams() CreateFlagParams { 24 | 25 | return CreateFlagParams{} 26 | } 27 | 28 | // CreateFlagParams contains all the bound params for the create flag operation 29 | // typically these are obtained from a http.Request 30 | // 31 | // swagger:parameters createFlag 32 | type CreateFlagParams struct { 33 | 34 | // HTTP Request Object 35 | HTTPRequest *http.Request `json:"-"` 36 | 37 | /*create a flag 38 | Required: true 39 | In: body 40 | */ 41 | Body *models.CreateFlagRequest 42 | } 43 | 44 | // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface 45 | // for simple values it will use straight method calls. 46 | // 47 | // To ensure default values, the struct must have been initialized with NewCreateFlagParams() beforehand. 48 | func (o *CreateFlagParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { 49 | var res []error 50 | 51 | o.HTTPRequest = r 52 | 53 | if runtime.HasBody(r) { 54 | defer r.Body.Close() 55 | var body models.CreateFlagRequest 56 | if err := route.Consumer.Consume(r.Body, &body); err != nil { 57 | if err == io.EOF { 58 | res = append(res, errors.Required("body", "body", "")) 59 | } else { 60 | res = append(res, errors.NewParseError("body", "body", "", err)) 61 | } 62 | } else { 63 | // validate body object 64 | if err := body.Validate(route.Formats); err != nil { 65 | res = append(res, err) 66 | } 67 | 68 | ctx := validate.WithOperationRequest(r.Context()) 69 | if err := body.ContextValidate(ctx, route.Formats); err != nil { 70 | res = append(res, err) 71 | } 72 | 73 | if len(res) == 0 { 74 | o.Body = &body 75 | } 76 | } 77 | } else { 78 | res = append(res, errors.Required("body", "body", "")) 79 | } 80 | if len(res) > 0 { 81 | return errors.CompositeValidationError(res...) 82 | } 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/create_flag_urlbuilder.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "errors" 10 | "net/url" 11 | golangswaggerpaths "path" 12 | ) 13 | 14 | // CreateFlagURL generates an URL for the create flag operation 15 | type CreateFlagURL struct { 16 | _basePath string 17 | } 18 | 19 | // WithBasePath sets the base path for this url builder, only required when it's different from the 20 | // base path specified in the swagger spec. 21 | // When the value of the base path is an empty string 22 | func (o *CreateFlagURL) WithBasePath(bp string) *CreateFlagURL { 23 | o.SetBasePath(bp) 24 | return o 25 | } 26 | 27 | // SetBasePath sets the base path for this url builder, only required when it's different from the 28 | // base path specified in the swagger spec. 29 | // When the value of the base path is an empty string 30 | func (o *CreateFlagURL) SetBasePath(bp string) { 31 | o._basePath = bp 32 | } 33 | 34 | // Build a url path and query string 35 | func (o *CreateFlagURL) Build() (*url.URL, error) { 36 | var _result url.URL 37 | 38 | var _path = "/flags" 39 | 40 | _basePath := o._basePath 41 | if _basePath == "" { 42 | _basePath = "/api/v1" 43 | } 44 | _result.Path = golangswaggerpaths.Join(_basePath, _path) 45 | 46 | return &_result, nil 47 | } 48 | 49 | // Must is a helper function to panic when the url builder returns an error 50 | func (o *CreateFlagURL) Must(u *url.URL, err error) *url.URL { 51 | if err != nil { 52 | panic(err) 53 | } 54 | if u == nil { 55 | panic("url can't be nil") 56 | } 57 | return u 58 | } 59 | 60 | // String returns the string representation of the path with query string 61 | func (o *CreateFlagURL) String() string { 62 | return o.Must(o.Build()).String() 63 | } 64 | 65 | // BuildFull builds a full url with scheme, host, path and query string 66 | func (o *CreateFlagURL) BuildFull(scheme, host string) (*url.URL, error) { 67 | if scheme == "" { 68 | return nil, errors.New("scheme is required for a full url on CreateFlagURL") 69 | } 70 | if host == "" { 71 | return nil, errors.New("host is required for a full url on CreateFlagURL") 72 | } 73 | 74 | base, err := o.Build() 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | base.Scheme = scheme 80 | base.Host = host 81 | return base, nil 82 | } 83 | 84 | // StringFull returns the string representation of a complete url 85 | func (o *CreateFlagURL) StringFull(scheme, host string) string { 86 | return o.Must(o.BuildFull(scheme, host)).String() 87 | } 88 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/delete_flag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // DeleteFlagHandlerFunc turns a function with the right signature into a delete flag handler 15 | type DeleteFlagHandlerFunc func(DeleteFlagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn DeleteFlagHandlerFunc) Handle(params DeleteFlagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // DeleteFlagHandler interface for that can handle valid delete flag params 23 | type DeleteFlagHandler interface { 24 | Handle(DeleteFlagParams) middleware.Responder 25 | } 26 | 27 | // NewDeleteFlag creates a new http.Handler for the delete flag operation 28 | func NewDeleteFlag(ctx *middleware.Context, handler DeleteFlagHandler) *DeleteFlag { 29 | return &DeleteFlag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | DeleteFlag swagger:route DELETE /flags/{flagID} flag deleteFlag 34 | 35 | DeleteFlag delete flag API 36 | */ 37 | type DeleteFlag struct { 38 | Context *middleware.Context 39 | Handler DeleteFlagHandler 40 | } 41 | 42 | func (o *DeleteFlag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewDeleteFlagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/find_flags.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindFlagsHandlerFunc turns a function with the right signature into a find flags handler 15 | type FindFlagsHandlerFunc func(FindFlagsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindFlagsHandlerFunc) Handle(params FindFlagsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindFlagsHandler interface for that can handle valid find flags params 23 | type FindFlagsHandler interface { 24 | Handle(FindFlagsParams) middleware.Responder 25 | } 26 | 27 | // NewFindFlags creates a new http.Handler for the find flags operation 28 | func NewFindFlags(ctx *middleware.Context, handler FindFlagsHandler) *FindFlags { 29 | return &FindFlags{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindFlags swagger:route GET /flags flag findFlags 34 | 35 | FindFlags find flags API 36 | */ 37 | type FindFlags struct { 38 | Context *middleware.Context 39 | Handler FindFlagsHandler 40 | } 41 | 42 | func (o *FindFlags) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindFlagsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/get_flag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // GetFlagHandlerFunc turns a function with the right signature into a get flag handler 15 | type GetFlagHandlerFunc func(GetFlagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn GetFlagHandlerFunc) Handle(params GetFlagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // GetFlagHandler interface for that can handle valid get flag params 23 | type GetFlagHandler interface { 24 | Handle(GetFlagParams) middleware.Responder 25 | } 26 | 27 | // NewGetFlag creates a new http.Handler for the get flag operation 28 | func NewGetFlag(ctx *middleware.Context, handler GetFlagHandler) *GetFlag { 29 | return &GetFlag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | GetFlag swagger:route GET /flags/{flagID} flag getFlag 34 | 35 | GetFlag get flag API 36 | */ 37 | type GetFlag struct { 38 | Context *middleware.Context 39 | Handler GetFlagHandler 40 | } 41 | 42 | func (o *GetFlag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewGetFlagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/get_flag_entity_types.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // GetFlagEntityTypesHandlerFunc turns a function with the right signature into a get flag entity types handler 15 | type GetFlagEntityTypesHandlerFunc func(GetFlagEntityTypesParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn GetFlagEntityTypesHandlerFunc) Handle(params GetFlagEntityTypesParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // GetFlagEntityTypesHandler interface for that can handle valid get flag entity types params 23 | type GetFlagEntityTypesHandler interface { 24 | Handle(GetFlagEntityTypesParams) middleware.Responder 25 | } 26 | 27 | // NewGetFlagEntityTypes creates a new http.Handler for the get flag entity types operation 28 | func NewGetFlagEntityTypes(ctx *middleware.Context, handler GetFlagEntityTypesHandler) *GetFlagEntityTypes { 29 | return &GetFlagEntityTypes{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | GetFlagEntityTypes swagger:route GET /flags/entity_types flag getFlagEntityTypes 34 | 35 | GetFlagEntityTypes get flag entity types API 36 | */ 37 | type GetFlagEntityTypes struct { 38 | Context *middleware.Context 39 | Handler GetFlagEntityTypesHandler 40 | } 41 | 42 | func (o *GetFlagEntityTypes) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewGetFlagEntityTypesParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/get_flag_entity_types_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/runtime/middleware" 13 | ) 14 | 15 | // NewGetFlagEntityTypesParams creates a new GetFlagEntityTypesParams object 16 | // 17 | // There are no default values defined in the spec. 18 | func NewGetFlagEntityTypesParams() GetFlagEntityTypesParams { 19 | 20 | return GetFlagEntityTypesParams{} 21 | } 22 | 23 | // GetFlagEntityTypesParams contains all the bound params for the get flag entity types operation 24 | // typically these are obtained from a http.Request 25 | // 26 | // swagger:parameters getFlagEntityTypes 27 | type GetFlagEntityTypesParams struct { 28 | 29 | // HTTP Request Object 30 | HTTPRequest *http.Request `json:"-"` 31 | } 32 | 33 | // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface 34 | // for simple values it will use straight method calls. 35 | // 36 | // To ensure default values, the struct must have been initialized with NewGetFlagEntityTypesParams() beforehand. 37 | func (o *GetFlagEntityTypesParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { 38 | var res []error 39 | 40 | o.HTTPRequest = r 41 | 42 | if len(res) > 0 { 43 | return errors.CompositeValidationError(res...) 44 | } 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/get_flag_snapshots.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // GetFlagSnapshotsHandlerFunc turns a function with the right signature into a get flag snapshots handler 15 | type GetFlagSnapshotsHandlerFunc func(GetFlagSnapshotsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn GetFlagSnapshotsHandlerFunc) Handle(params GetFlagSnapshotsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // GetFlagSnapshotsHandler interface for that can handle valid get flag snapshots params 23 | type GetFlagSnapshotsHandler interface { 24 | Handle(GetFlagSnapshotsParams) middleware.Responder 25 | } 26 | 27 | // NewGetFlagSnapshots creates a new http.Handler for the get flag snapshots operation 28 | func NewGetFlagSnapshots(ctx *middleware.Context, handler GetFlagSnapshotsHandler) *GetFlagSnapshots { 29 | return &GetFlagSnapshots{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | GetFlagSnapshots swagger:route GET /flags/{flagID}/snapshots flag getFlagSnapshots 34 | 35 | GetFlagSnapshots get flag snapshots API 36 | */ 37 | type GetFlagSnapshots struct { 38 | Context *middleware.Context 39 | Handler GetFlagSnapshotsHandler 40 | } 41 | 42 | func (o *GetFlagSnapshots) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewGetFlagSnapshotsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/put_flag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PutFlagHandlerFunc turns a function with the right signature into a put flag handler 15 | type PutFlagHandlerFunc func(PutFlagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PutFlagHandlerFunc) Handle(params PutFlagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PutFlagHandler interface for that can handle valid put flag params 23 | type PutFlagHandler interface { 24 | Handle(PutFlagParams) middleware.Responder 25 | } 26 | 27 | // NewPutFlag creates a new http.Handler for the put flag operation 28 | func NewPutFlag(ctx *middleware.Context, handler PutFlagHandler) *PutFlag { 29 | return &PutFlag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PutFlag swagger:route PUT /flags/{flagID} flag putFlag 34 | 35 | PutFlag put flag API 36 | */ 37 | type PutFlag struct { 38 | Context *middleware.Context 39 | Handler PutFlagHandler 40 | } 41 | 42 | func (o *PutFlag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPutFlagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/restore_flag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // RestoreFlagHandlerFunc turns a function with the right signature into a restore flag handler 15 | type RestoreFlagHandlerFunc func(RestoreFlagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn RestoreFlagHandlerFunc) Handle(params RestoreFlagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // RestoreFlagHandler interface for that can handle valid restore flag params 23 | type RestoreFlagHandler interface { 24 | Handle(RestoreFlagParams) middleware.Responder 25 | } 26 | 27 | // NewRestoreFlag creates a new http.Handler for the restore flag operation 28 | func NewRestoreFlag(ctx *middleware.Context, handler RestoreFlagHandler) *RestoreFlag { 29 | return &RestoreFlag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | RestoreFlag swagger:route PUT /flags/{flagID}/restore flag restoreFlag 34 | 35 | RestoreFlag restore flag API 36 | */ 37 | type RestoreFlag struct { 38 | Context *middleware.Context 39 | Handler RestoreFlagHandler 40 | } 41 | 42 | func (o *RestoreFlag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewRestoreFlagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/flag/set_flag_enabled.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package flag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // SetFlagEnabledHandlerFunc turns a function with the right signature into a set flag enabled handler 15 | type SetFlagEnabledHandlerFunc func(SetFlagEnabledParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn SetFlagEnabledHandlerFunc) Handle(params SetFlagEnabledParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // SetFlagEnabledHandler interface for that can handle valid set flag enabled params 23 | type SetFlagEnabledHandler interface { 24 | Handle(SetFlagEnabledParams) middleware.Responder 25 | } 26 | 27 | // NewSetFlagEnabled creates a new http.Handler for the set flag enabled operation 28 | func NewSetFlagEnabled(ctx *middleware.Context, handler SetFlagEnabledHandler) *SetFlagEnabled { 29 | return &SetFlagEnabled{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | SetFlagEnabled swagger:route PUT /flags/{flagID}/enabled flag setFlagEnabled 34 | 35 | SetFlagEnabled set flag enabled API 36 | */ 37 | type SetFlagEnabled struct { 38 | Context *middleware.Context 39 | Handler SetFlagEnabledHandler 40 | } 41 | 42 | func (o *SetFlagEnabled) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewSetFlagEnabledParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/health/get_health.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package health 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // GetHealthHandlerFunc turns a function with the right signature into a get health handler 15 | type GetHealthHandlerFunc func(GetHealthParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn GetHealthHandlerFunc) Handle(params GetHealthParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // GetHealthHandler interface for that can handle valid get health params 23 | type GetHealthHandler interface { 24 | Handle(GetHealthParams) middleware.Responder 25 | } 26 | 27 | // NewGetHealth creates a new http.Handler for the get health operation 28 | func NewGetHealth(ctx *middleware.Context, handler GetHealthHandler) *GetHealth { 29 | return &GetHealth{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | GetHealth swagger:route GET /health health getHealth 34 | 35 | Check if Flagr is healthy 36 | */ 37 | type GetHealth struct { 38 | Context *middleware.Context 39 | Handler GetHealthHandler 40 | } 41 | 42 | func (o *GetHealth) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewGetHealthParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/health/get_health_parameters.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package health 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/errors" 12 | "github.com/go-openapi/runtime/middleware" 13 | ) 14 | 15 | // NewGetHealthParams creates a new GetHealthParams object 16 | // 17 | // There are no default values defined in the spec. 18 | func NewGetHealthParams() GetHealthParams { 19 | 20 | return GetHealthParams{} 21 | } 22 | 23 | // GetHealthParams contains all the bound params for the get health operation 24 | // typically these are obtained from a http.Request 25 | // 26 | // swagger:parameters getHealth 27 | type GetHealthParams struct { 28 | 29 | // HTTP Request Object 30 | HTTPRequest *http.Request `json:"-"` 31 | } 32 | 33 | // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface 34 | // for simple values it will use straight method calls. 35 | // 36 | // To ensure default values, the struct must have been initialized with NewGetHealthParams() beforehand. 37 | func (o *GetHealthParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { 38 | var res []error 39 | 40 | o.HTTPRequest = r 41 | 42 | if len(res) > 0 { 43 | return errors.CompositeValidationError(res...) 44 | } 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/health/get_health_urlbuilder.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package health 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "errors" 10 | "net/url" 11 | golangswaggerpaths "path" 12 | ) 13 | 14 | // GetHealthURL generates an URL for the get health operation 15 | type GetHealthURL struct { 16 | _basePath string 17 | } 18 | 19 | // WithBasePath sets the base path for this url builder, only required when it's different from the 20 | // base path specified in the swagger spec. 21 | // When the value of the base path is an empty string 22 | func (o *GetHealthURL) WithBasePath(bp string) *GetHealthURL { 23 | o.SetBasePath(bp) 24 | return o 25 | } 26 | 27 | // SetBasePath sets the base path for this url builder, only required when it's different from the 28 | // base path specified in the swagger spec. 29 | // When the value of the base path is an empty string 30 | func (o *GetHealthURL) SetBasePath(bp string) { 31 | o._basePath = bp 32 | } 33 | 34 | // Build a url path and query string 35 | func (o *GetHealthURL) Build() (*url.URL, error) { 36 | var _result url.URL 37 | 38 | var _path = "/health" 39 | 40 | _basePath := o._basePath 41 | if _basePath == "" { 42 | _basePath = "/api/v1" 43 | } 44 | _result.Path = golangswaggerpaths.Join(_basePath, _path) 45 | 46 | return &_result, nil 47 | } 48 | 49 | // Must is a helper function to panic when the url builder returns an error 50 | func (o *GetHealthURL) Must(u *url.URL, err error) *url.URL { 51 | if err != nil { 52 | panic(err) 53 | } 54 | if u == nil { 55 | panic("url can't be nil") 56 | } 57 | return u 58 | } 59 | 60 | // String returns the string representation of the path with query string 61 | func (o *GetHealthURL) String() string { 62 | return o.Must(o.Build()).String() 63 | } 64 | 65 | // BuildFull builds a full url with scheme, host, path and query string 66 | func (o *GetHealthURL) BuildFull(scheme, host string) (*url.URL, error) { 67 | if scheme == "" { 68 | return nil, errors.New("scheme is required for a full url on GetHealthURL") 69 | } 70 | if host == "" { 71 | return nil, errors.New("host is required for a full url on GetHealthURL") 72 | } 73 | 74 | base, err := o.Build() 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | base.Scheme = scheme 80 | base.Host = host 81 | return base, nil 82 | } 83 | 84 | // StringFull returns the string representation of a complete url 85 | func (o *GetHealthURL) StringFull(scheme, host string) string { 86 | return o.Must(o.BuildFull(scheme, host)).String() 87 | } 88 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/segment/create_segment.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package segment 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // CreateSegmentHandlerFunc turns a function with the right signature into a create segment handler 15 | type CreateSegmentHandlerFunc func(CreateSegmentParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn CreateSegmentHandlerFunc) Handle(params CreateSegmentParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // CreateSegmentHandler interface for that can handle valid create segment params 23 | type CreateSegmentHandler interface { 24 | Handle(CreateSegmentParams) middleware.Responder 25 | } 26 | 27 | // NewCreateSegment creates a new http.Handler for the create segment operation 28 | func NewCreateSegment(ctx *middleware.Context, handler CreateSegmentHandler) *CreateSegment { 29 | return &CreateSegment{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | CreateSegment swagger:route POST /flags/{flagID}/segments segment createSegment 34 | 35 | CreateSegment create segment API 36 | */ 37 | type CreateSegment struct { 38 | Context *middleware.Context 39 | Handler CreateSegmentHandler 40 | } 41 | 42 | func (o *CreateSegment) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewCreateSegmentParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/segment/delete_segment.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package segment 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // DeleteSegmentHandlerFunc turns a function with the right signature into a delete segment handler 15 | type DeleteSegmentHandlerFunc func(DeleteSegmentParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn DeleteSegmentHandlerFunc) Handle(params DeleteSegmentParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // DeleteSegmentHandler interface for that can handle valid delete segment params 23 | type DeleteSegmentHandler interface { 24 | Handle(DeleteSegmentParams) middleware.Responder 25 | } 26 | 27 | // NewDeleteSegment creates a new http.Handler for the delete segment operation 28 | func NewDeleteSegment(ctx *middleware.Context, handler DeleteSegmentHandler) *DeleteSegment { 29 | return &DeleteSegment{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | DeleteSegment swagger:route DELETE /flags/{flagID}/segments/{segmentID} segment deleteSegment 34 | 35 | DeleteSegment delete segment API 36 | */ 37 | type DeleteSegment struct { 38 | Context *middleware.Context 39 | Handler DeleteSegmentHandler 40 | } 41 | 42 | func (o *DeleteSegment) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewDeleteSegmentParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/segment/find_segments.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package segment 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindSegmentsHandlerFunc turns a function with the right signature into a find segments handler 15 | type FindSegmentsHandlerFunc func(FindSegmentsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindSegmentsHandlerFunc) Handle(params FindSegmentsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindSegmentsHandler interface for that can handle valid find segments params 23 | type FindSegmentsHandler interface { 24 | Handle(FindSegmentsParams) middleware.Responder 25 | } 26 | 27 | // NewFindSegments creates a new http.Handler for the find segments operation 28 | func NewFindSegments(ctx *middleware.Context, handler FindSegmentsHandler) *FindSegments { 29 | return &FindSegments{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindSegments swagger:route GET /flags/{flagID}/segments segment findSegments 34 | 35 | FindSegments find segments API 36 | */ 37 | type FindSegments struct { 38 | Context *middleware.Context 39 | Handler FindSegmentsHandler 40 | } 41 | 42 | func (o *FindSegments) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindSegmentsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/segment/put_segment.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package segment 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PutSegmentHandlerFunc turns a function with the right signature into a put segment handler 15 | type PutSegmentHandlerFunc func(PutSegmentParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PutSegmentHandlerFunc) Handle(params PutSegmentParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PutSegmentHandler interface for that can handle valid put segment params 23 | type PutSegmentHandler interface { 24 | Handle(PutSegmentParams) middleware.Responder 25 | } 26 | 27 | // NewPutSegment creates a new http.Handler for the put segment operation 28 | func NewPutSegment(ctx *middleware.Context, handler PutSegmentHandler) *PutSegment { 29 | return &PutSegment{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PutSegment swagger:route PUT /flags/{flagID}/segments/{segmentID} segment putSegment 34 | 35 | PutSegment put segment API 36 | */ 37 | type PutSegment struct { 38 | Context *middleware.Context 39 | Handler PutSegmentHandler 40 | } 41 | 42 | func (o *PutSegment) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPutSegmentParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/segment/put_segments_reorder.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package segment 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PutSegmentsReorderHandlerFunc turns a function with the right signature into a put segments reorder handler 15 | type PutSegmentsReorderHandlerFunc func(PutSegmentsReorderParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PutSegmentsReorderHandlerFunc) Handle(params PutSegmentsReorderParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PutSegmentsReorderHandler interface for that can handle valid put segments reorder params 23 | type PutSegmentsReorderHandler interface { 24 | Handle(PutSegmentsReorderParams) middleware.Responder 25 | } 26 | 27 | // NewPutSegmentsReorder creates a new http.Handler for the put segments reorder operation 28 | func NewPutSegmentsReorder(ctx *middleware.Context, handler PutSegmentsReorderHandler) *PutSegmentsReorder { 29 | return &PutSegmentsReorder{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PutSegmentsReorder swagger:route PUT /flags/{flagID}/segments/reorder segment putSegmentsReorder 34 | 35 | PutSegmentsReorder put segments reorder API 36 | */ 37 | type PutSegmentsReorder struct { 38 | Context *middleware.Context 39 | Handler PutSegmentsReorderHandler 40 | } 41 | 42 | func (o *PutSegmentsReorder) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPutSegmentsReorderParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/tag/create_tag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package tag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // CreateTagHandlerFunc turns a function with the right signature into a create tag handler 15 | type CreateTagHandlerFunc func(CreateTagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn CreateTagHandlerFunc) Handle(params CreateTagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // CreateTagHandler interface for that can handle valid create tag params 23 | type CreateTagHandler interface { 24 | Handle(CreateTagParams) middleware.Responder 25 | } 26 | 27 | // NewCreateTag creates a new http.Handler for the create tag operation 28 | func NewCreateTag(ctx *middleware.Context, handler CreateTagHandler) *CreateTag { 29 | return &CreateTag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | CreateTag swagger:route POST /flags/{flagID}/tags tag createTag 34 | 35 | CreateTag create tag API 36 | */ 37 | type CreateTag struct { 38 | Context *middleware.Context 39 | Handler CreateTagHandler 40 | } 41 | 42 | func (o *CreateTag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewCreateTagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/tag/delete_tag.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package tag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // DeleteTagHandlerFunc turns a function with the right signature into a delete tag handler 15 | type DeleteTagHandlerFunc func(DeleteTagParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn DeleteTagHandlerFunc) Handle(params DeleteTagParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // DeleteTagHandler interface for that can handle valid delete tag params 23 | type DeleteTagHandler interface { 24 | Handle(DeleteTagParams) middleware.Responder 25 | } 26 | 27 | // NewDeleteTag creates a new http.Handler for the delete tag operation 28 | func NewDeleteTag(ctx *middleware.Context, handler DeleteTagHandler) *DeleteTag { 29 | return &DeleteTag{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | DeleteTag swagger:route DELETE /flags/{flagID}/tags/{tagID} tag deleteTag 34 | 35 | DeleteTag delete tag API 36 | */ 37 | type DeleteTag struct { 38 | Context *middleware.Context 39 | Handler DeleteTagHandler 40 | } 41 | 42 | func (o *DeleteTag) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewDeleteTagParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/tag/delete_tag_responses.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package tag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the swagger generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime" 12 | 13 | "github.com/openflagr/flagr/swagger_gen/models" 14 | ) 15 | 16 | // DeleteTagOKCode is the HTTP code returned for type DeleteTagOK 17 | const DeleteTagOKCode int = 200 18 | 19 | /* 20 | DeleteTagOK deleted 21 | 22 | swagger:response deleteTagOK 23 | */ 24 | type DeleteTagOK struct { 25 | } 26 | 27 | // NewDeleteTagOK creates DeleteTagOK with default headers values 28 | func NewDeleteTagOK() *DeleteTagOK { 29 | 30 | return &DeleteTagOK{} 31 | } 32 | 33 | // WriteResponse to the client 34 | func (o *DeleteTagOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { 35 | 36 | rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses 37 | 38 | rw.WriteHeader(200) 39 | } 40 | 41 | /* 42 | DeleteTagDefault generic error response 43 | 44 | swagger:response deleteTagDefault 45 | */ 46 | type DeleteTagDefault struct { 47 | _statusCode int 48 | 49 | /* 50 | In: Body 51 | */ 52 | Payload *models.Error `json:"body,omitempty"` 53 | } 54 | 55 | // NewDeleteTagDefault creates DeleteTagDefault with default headers values 56 | func NewDeleteTagDefault(code int) *DeleteTagDefault { 57 | if code <= 0 { 58 | code = 500 59 | } 60 | 61 | return &DeleteTagDefault{ 62 | _statusCode: code, 63 | } 64 | } 65 | 66 | // WithStatusCode adds the status to the delete tag default response 67 | func (o *DeleteTagDefault) WithStatusCode(code int) *DeleteTagDefault { 68 | o._statusCode = code 69 | return o 70 | } 71 | 72 | // SetStatusCode sets the status to the delete tag default response 73 | func (o *DeleteTagDefault) SetStatusCode(code int) { 74 | o._statusCode = code 75 | } 76 | 77 | // WithPayload adds the payload to the delete tag default response 78 | func (o *DeleteTagDefault) WithPayload(payload *models.Error) *DeleteTagDefault { 79 | o.Payload = payload 80 | return o 81 | } 82 | 83 | // SetPayload sets the payload to the delete tag default response 84 | func (o *DeleteTagDefault) SetPayload(payload *models.Error) { 85 | o.Payload = payload 86 | } 87 | 88 | // WriteResponse to the client 89 | func (o *DeleteTagDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { 90 | 91 | rw.WriteHeader(o._statusCode) 92 | if o.Payload != nil { 93 | payload := o.Payload 94 | if err := producer.Produce(rw, payload); err != nil { 95 | panic(err) // let the recovery middleware deal with this 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/tag/find_all_tags.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package tag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindAllTagsHandlerFunc turns a function with the right signature into a find all tags handler 15 | type FindAllTagsHandlerFunc func(FindAllTagsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindAllTagsHandlerFunc) Handle(params FindAllTagsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindAllTagsHandler interface for that can handle valid find all tags params 23 | type FindAllTagsHandler interface { 24 | Handle(FindAllTagsParams) middleware.Responder 25 | } 26 | 27 | // NewFindAllTags creates a new http.Handler for the find all tags operation 28 | func NewFindAllTags(ctx *middleware.Context, handler FindAllTagsHandler) *FindAllTags { 29 | return &FindAllTags{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindAllTags swagger:route GET /tags tag findAllTags 34 | 35 | FindAllTags find all tags API 36 | */ 37 | type FindAllTags struct { 38 | Context *middleware.Context 39 | Handler FindAllTagsHandler 40 | } 41 | 42 | func (o *FindAllTags) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindAllTagsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/tag/find_tags.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package tag 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindTagsHandlerFunc turns a function with the right signature into a find tags handler 15 | type FindTagsHandlerFunc func(FindTagsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindTagsHandlerFunc) Handle(params FindTagsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindTagsHandler interface for that can handle valid find tags params 23 | type FindTagsHandler interface { 24 | Handle(FindTagsParams) middleware.Responder 25 | } 26 | 27 | // NewFindTags creates a new http.Handler for the find tags operation 28 | func NewFindTags(ctx *middleware.Context, handler FindTagsHandler) *FindTags { 29 | return &FindTags{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindTags swagger:route GET /flags/{flagID}/tags tag findTags 34 | 35 | FindTags find tags API 36 | */ 37 | type FindTags struct { 38 | Context *middleware.Context 39 | Handler FindTagsHandler 40 | } 41 | 42 | func (o *FindTags) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindTagsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/variant/create_variant.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package variant 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // CreateVariantHandlerFunc turns a function with the right signature into a create variant handler 15 | type CreateVariantHandlerFunc func(CreateVariantParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn CreateVariantHandlerFunc) Handle(params CreateVariantParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // CreateVariantHandler interface for that can handle valid create variant params 23 | type CreateVariantHandler interface { 24 | Handle(CreateVariantParams) middleware.Responder 25 | } 26 | 27 | // NewCreateVariant creates a new http.Handler for the create variant operation 28 | func NewCreateVariant(ctx *middleware.Context, handler CreateVariantHandler) *CreateVariant { 29 | return &CreateVariant{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | CreateVariant swagger:route POST /flags/{flagID}/variants variant createVariant 34 | 35 | CreateVariant create variant API 36 | */ 37 | type CreateVariant struct { 38 | Context *middleware.Context 39 | Handler CreateVariantHandler 40 | } 41 | 42 | func (o *CreateVariant) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewCreateVariantParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/variant/delete_variant.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package variant 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // DeleteVariantHandlerFunc turns a function with the right signature into a delete variant handler 15 | type DeleteVariantHandlerFunc func(DeleteVariantParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn DeleteVariantHandlerFunc) Handle(params DeleteVariantParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // DeleteVariantHandler interface for that can handle valid delete variant params 23 | type DeleteVariantHandler interface { 24 | Handle(DeleteVariantParams) middleware.Responder 25 | } 26 | 27 | // NewDeleteVariant creates a new http.Handler for the delete variant operation 28 | func NewDeleteVariant(ctx *middleware.Context, handler DeleteVariantHandler) *DeleteVariant { 29 | return &DeleteVariant{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | DeleteVariant swagger:route DELETE /flags/{flagID}/variants/{variantID} variant deleteVariant 34 | 35 | DeleteVariant delete variant API 36 | */ 37 | type DeleteVariant struct { 38 | Context *middleware.Context 39 | Handler DeleteVariantHandler 40 | } 41 | 42 | func (o *DeleteVariant) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewDeleteVariantParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/variant/find_variants.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package variant 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // FindVariantsHandlerFunc turns a function with the right signature into a find variants handler 15 | type FindVariantsHandlerFunc func(FindVariantsParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn FindVariantsHandlerFunc) Handle(params FindVariantsParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // FindVariantsHandler interface for that can handle valid find variants params 23 | type FindVariantsHandler interface { 24 | Handle(FindVariantsParams) middleware.Responder 25 | } 26 | 27 | // NewFindVariants creates a new http.Handler for the find variants operation 28 | func NewFindVariants(ctx *middleware.Context, handler FindVariantsHandler) *FindVariants { 29 | return &FindVariants{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | FindVariants swagger:route GET /flags/{flagID}/variants variant findVariants 34 | 35 | FindVariants find variants API 36 | */ 37 | type FindVariants struct { 38 | Context *middleware.Context 39 | Handler FindVariantsHandler 40 | } 41 | 42 | func (o *FindVariants) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewFindVariantsParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | -------------------------------------------------------------------------------- /swagger_gen/restapi/operations/variant/put_variant.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-swagger; DO NOT EDIT. 2 | 3 | package variant 4 | 5 | // This file was generated by the swagger tool. 6 | // Editing this file might prove futile when you re-run the generate command 7 | 8 | import ( 9 | "net/http" 10 | 11 | "github.com/go-openapi/runtime/middleware" 12 | ) 13 | 14 | // PutVariantHandlerFunc turns a function with the right signature into a put variant handler 15 | type PutVariantHandlerFunc func(PutVariantParams) middleware.Responder 16 | 17 | // Handle executing the request and returning a response 18 | func (fn PutVariantHandlerFunc) Handle(params PutVariantParams) middleware.Responder { 19 | return fn(params) 20 | } 21 | 22 | // PutVariantHandler interface for that can handle valid put variant params 23 | type PutVariantHandler interface { 24 | Handle(PutVariantParams) middleware.Responder 25 | } 26 | 27 | // NewPutVariant creates a new http.Handler for the put variant operation 28 | func NewPutVariant(ctx *middleware.Context, handler PutVariantHandler) *PutVariant { 29 | return &PutVariant{Context: ctx, Handler: handler} 30 | } 31 | 32 | /* 33 | PutVariant swagger:route PUT /flags/{flagID}/variants/{variantID} variant putVariant 34 | 35 | PutVariant put variant API 36 | */ 37 | type PutVariant struct { 38 | Context *middleware.Context 39 | Handler PutVariantHandler 40 | } 41 | 42 | func (o *PutVariant) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 43 | route, rCtx, _ := o.Context.RouteInfo(r) 44 | if rCtx != nil { 45 | *r = *rCtx 46 | } 47 | var Params = NewPutVariantParams() 48 | if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params 49 | o.Context.Respond(rw, r, route.Produces, route, err) 50 | return 51 | } 52 | 53 | res := o.Handler.Handle(Params) // actually handle the request 54 | o.Context.Respond(rw, r, route.Produces, route, res) 55 | 56 | } 57 | --------------------------------------------------------------------------------