├── .github
├── generate-reports.sh
└── workflows
│ ├── ci.yml
│ ├── e2e-test.yml
│ └── helm.yaml
├── .gitignore
├── .licenserc.yaml
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README-CN.md
├── README.md
├── SECURITY.md
├── VERSION
├── build
└── build.sh
├── charts
└── bfe-ingress-controller
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── rbac.yaml
│ ├── service.yaml
│ └── serviceaccount.yaml
│ └── values.yaml
├── cmd
└── ingress-controller
│ ├── flags.go
│ └── main.go
├── dist
├── bfe.ini
└── start.sh
├── docs
├── en_us
│ ├── FAQ
│ │ └── FAQ.md
│ ├── README.md
│ ├── SUMMARY.md
│ ├── appendix
│ │ └── annotations.md
│ ├── contribute
│ │ ├── contribute-codes.md
│ │ ├── contribute-documents.md
│ │ └── how-to-contribute.md
│ ├── deployment.md
│ ├── example
│ │ ├── canary-release.md
│ │ └── example.md
│ ├── ingress
│ │ ├── basic.md
│ │ ├── conflict.md
│ │ ├── load-balance.md
│ │ ├── priority.md
│ │ ├── redirect.md
│ │ ├── rewrite.md
│ │ ├── tls.md
│ │ └── validate-state.md
│ └── rbac.md
├── images
│ ├── arch.jpg
│ └── qrcode_for_gh.jpg
└── zh_cn
│ ├── FAQ
│ └── FAQ.md
│ ├── README.md
│ ├── SUMMARY.md
│ ├── appendix
│ └── annotations.md
│ ├── contribute
│ ├── contribute-codes.md
│ ├── contribute-documents.md
│ └── how-to-contribute.md
│ ├── deployment.md
│ ├── development
│ ├── annotation-implement-guide.md
│ ├── core-logic.md
│ └── source-code-layout.md
│ ├── example
│ ├── canary-release.md
│ ├── example.md
│ └── example.md.orig
│ ├── ingress
│ ├── basic.md
│ ├── conflict.md
│ ├── load-balance.md
│ ├── priority.md
│ ├── redirect.md
│ ├── rewrite.md
│ ├── tls.md
│ └── validate-state.md
│ └── rbac.md
├── examples
├── controller-all.yaml
├── controller.yaml
├── ingress-v1.19.yaml
├── ingress.yaml
├── rbac.yaml
└── whoami.yaml
├── go.mod
├── go.sum
├── internal
├── bfeConfig
│ ├── annotations
│ │ ├── annotation.go
│ │ ├── balance.go
│ │ ├── balance_test.go
│ │ ├── priority.go
│ │ ├── redirect.go
│ │ ├── rewrite.go
│ │ ├── rewrite_test.go
│ │ ├── router.go
│ │ ├── router_test.go
│ │ └── status.go
│ ├── configBuilder.go
│ ├── configs
│ │ ├── TLSConfig.go
│ │ ├── cache
│ │ │ ├── baseCache.go
│ │ │ ├── baseRule.go
│ │ │ └── rule.go
│ │ ├── clusterConfig.go
│ │ ├── log
│ │ │ └── log.go
│ │ ├── modules
│ │ │ ├── module.go
│ │ │ ├── redirect
│ │ │ │ ├── cache.go
│ │ │ │ └── redirect.go
│ │ │ └── rewrite
│ │ │ │ ├── cache.go
│ │ │ │ └── rewrite.go
│ │ ├── routeRuleCache.go
│ │ ├── routeRuleCache_test.go
│ │ └── serverDataConfig.go
│ └── util
│ │ ├── io.go
│ │ ├── name.go
│ │ └── version.go
├── controllers
│ ├── event
│ │ └── events.go
│ ├── filter
│ │ ├── ingressClass.go
│ │ ├── ingressClass_test.go
│ │ └── namespace.go
│ ├── ingress
│ │ ├── extv1beta1
│ │ │ └── ingress_controller.go
│ │ ├── netv1
│ │ │ └── ingress_controller.go
│ │ ├── netv1beta1
│ │ │ └── ingress_controller.go
│ │ ├── secret_controller.go
│ │ └── service_controller.go
│ └── start.go
└── option
│ ├── ingress
│ └── options.go
│ └── options.go
├── scripts
└── start.sh
└── test
├── e2e
├── Dockerfile
├── Makefile
├── README.md
├── e2e_test.go
├── features
│ ├── annotations
│ │ ├── balance
│ │ │ └── load_balance.feature
│ │ ├── redirect
│ │ │ └── redirect.feature
│ │ ├── rewrite
│ │ │ └── rewrite.feature
│ │ └── route
│ │ │ ├── cookie.feature
│ │ │ ├── header.feature
│ │ │ └── priority.feature
│ ├── conformance
│ │ ├── default_backend.feature
│ │ ├── host_rules.feature
│ │ ├── ingress_class.feature
│ │ ├── load_balancing.feature
│ │ └── path_rules.feature
│ └── rules
│ │ ├── host_rule1.feature
│ │ ├── host_rule2.feature
│ │ ├── multiple_ingress.feature
│ │ ├── path_err.feature
│ │ ├── path_rule1.feature
│ │ └── path_rule2.feature
├── go.mod
├── go.sum
├── hack
│ ├── boilerplate
│ │ ├── boilerplate.go.txt
│ │ ├── boilerplate.py
│ │ ├── boilerplate.py.txt
│ │ └── boilerplate.sh.txt
│ ├── check-go-version.sh
│ ├── codegen.go
│ ├── codegen.tmpl
│ ├── kube-env.sh
│ ├── verify-all.sh
│ ├── verify-boilerplate.sh
│ ├── verify-gherkin.sh
│ ├── verify-gofmt.sh
│ └── verify-golint.sh
├── images
│ ├── echoserver
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── echoserver
│ │ └── echoserver.go
│ └── reports
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── README.md
│ │ └── src
│ │ ├── .gitignore
│ │ ├── cucumber-html-reporter
│ │ ├── .eslintrc.yml
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.MD
│ │ ├── lib
│ │ │ ├── collect-jsons.js
│ │ │ ├── generate-report.js
│ │ │ ├── parse.cucumber.data.js
│ │ │ └── utils.js
│ │ ├── package.json
│ │ └── templates
│ │ │ ├── components
│ │ │ ├── features-overview.chart.ejs
│ │ │ ├── features-overview.ejs
│ │ │ ├── scenarios-overview.chart.ejs
│ │ │ └── scenarios.ejs
│ │ │ ├── feature-overview.index.ejs
│ │ │ ├── features-overview.index.ejs
│ │ │ ├── generic.js
│ │ │ └── style.css
│ │ ├── index.js
│ │ └── package.json
├── pkg
│ ├── files
│ │ └── files.go
│ ├── http
│ │ └── http.go
│ ├── kubernetes
│ │ ├── deployment.go
│ │ ├── kubernetes.go
│ │ └── templates
│ │ │ └── templates.go
│ └── state
│ │ └── state.go
├── run.sh
└── steps
│ ├── annotations
│ ├── balance
│ │ └── loadbalance
│ │ │ └── steps.go
│ ├── redirect
│ │ └── steps.go
│ ├── rewrite
│ │ └── steps.go
│ └── route
│ │ ├── cookie
│ │ └── steps.go
│ │ ├── header
│ │ └── steps.go
│ │ └── priority
│ │ └── steps.go
│ ├── conformance
│ ├── defaultbackend
│ │ └── steps.go
│ ├── hostrules
│ │ └── steps.go
│ ├── ingressclass
│ │ └── steps.go
│ ├── loadbalancing
│ │ └── steps.go
│ └── pathrules
│ │ └── steps.go
│ └── rules
│ ├── host1
│ └── steps.go
│ ├── host2
│ └── steps.go
│ ├── multipleingress
│ └── steps.go
│ ├── path1
│ └── steps.go
│ ├── path2
│ └── steps.go
│ └── patherr
│ └── steps.go
└── script
├── controller-svc.yaml
├── deploy-controller.sh
├── ingressclass.yaml
├── kind-config.yaml
├── kind-create-cluster.sh
├── kind-delete-cluster.sh
└── kind-load-images.sh
/.github/generate-reports.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2020 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -o errexit
18 | set -o nounset
19 | set -o pipefail
20 | set -x
21 |
22 | (cd "$(dirname "$0")/../test/e2e/images/reports" && make build-image)
23 |
24 | REPORT_BUILDER_IMAGE=local/reports-builder:0.0.1
25 |
26 | REPORTS_DIR=${REPORTS_DIR:-/tmp/bfe-ingress-reports}
27 |
28 | INGRESS_CONTROLLER="BFE-ingress-controller"
29 | CONTROLLER_VERSION=${CONTROLLER_VERSION:-'N/A'}
30 |
31 | TEMP_CONTENT=$(mktemp -d)
32 |
33 | docker run \
34 | -e BUILD="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
35 | -e INPUT_DIRECTORY=/input \
36 | -e OUTPUT_DIRECTORY=/output \
37 | -e INGRESS_CONTROLLER="${INGRESS_CONTROLLER}" \
38 | -e CONTROLLER_VERSION="${CONTROLLER_VERSION}" \
39 | -v "${REPORTS_DIR}":/input:ro \
40 | -v "${TEMP_CONTENT}":/output \
41 | -u "$(id -u):$(id -g)" \
42 | "${REPORT_BUILDER_IMAGE}"
43 |
44 | pushd "${TEMP_WORKTREE}" > /dev/null
45 |
46 | if [[ -d ./e2e-test ]]; then
47 | git rm -r ./e2e-test
48 | else
49 | mkdir -p "${TEMP_WORKTREE}/e2e-test"
50 | fi
51 |
52 | # copy new content
53 | cp -r -a "${TEMP_CONTENT}/." "${TEMP_WORKTREE}/e2e-test/"
54 |
55 | # cleanup HTML
56 | sudo apt-get install tidy
57 | for html_file in e2e-test/*.html;do
58 | tidy -q --break-before-br no --tidy-mark no --show-warnings no --wrap 0 -indent -m "$html_file" || true
59 | done
60 |
61 | # configure git
62 | git config --global user.email "action@github.com"
63 | git config --global user.name "GitHub Action"
64 | # commit changes
65 | git add e2e-test
66 | git commit -m "e2e test report"
67 | git push --force --quiet
68 |
69 | popd > /dev/null
70 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # This is a basic workflow to help you get started with Actions
16 |
17 | name: CI
18 |
19 | # Controls when the action will run. Triggers the workflow on push or pull request
20 | # events but only for the master branch
21 | on:
22 | push:
23 | branches: [ develop ]
24 | pull_request:
25 | branches: [ develop ]
26 |
27 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
28 | jobs:
29 | # This workflow contains a single job called "ci"
30 | ci:
31 | # The type of runner that the job will run on
32 | runs-on: ubuntu-latest
33 |
34 | # Steps represent a sequence of tasks that will be executed as part of the job
35 | steps:
36 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
37 | - name: Checkout repository
38 | uses: actions/checkout@v2
39 | with:
40 | # Must fetch at least the immediate parents so that if this is
41 | # a pull request then we can checkout the head of the pull request.
42 | # Only include this option if you are running this workflow on pull requests.
43 | fetch-depth: 2
44 |
45 | # If this run was triggered by a pull request event then checkout
46 | # the head of the pull request instead of the merge commit.
47 | # Only include this step if you are running this workflow on pull requests.
48 | - run: git checkout HEAD^2
49 | if: ${{ github.event_name == 'pull_request' }}
50 |
51 | # Build
52 | - name: Build
53 | shell: bash
54 | run: |
55 | make
56 |
--------------------------------------------------------------------------------
/.github/workflows/e2e-test.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # This is a basic workflow to help you get started with Actions
16 |
17 | name: e2e-test
18 |
19 | # Controls when the action will run. Triggers the workflow on push or pull request
20 | # events but only for the master branch
21 | on:
22 | push:
23 | branches: [ main, develop ]
24 | pull_request:
25 | branches: [ develop ]
26 |
27 | permissions:
28 | actions: read
29 | checks: read
30 | contents: write
31 | deployments: read
32 | discussions: read
33 | issues: read
34 | pages: read
35 | packages: read
36 | pull-requests: write
37 | repository-projects: read
38 | security-events: read
39 | statuses: read
40 |
41 | jobs:
42 | e2e-test:
43 | runs-on: ubuntu-latest
44 | environment: e2e
45 |
46 | env:
47 | CUCUMBER_FEATURE: ${{ secrets.CUCUMBER_FEATURE }}
48 | WAIT_FOR_STATUS_TIMEOUT: ${{ secrets.WAIT_FOR_STATUS_TIMEOUT }}
49 | TEST_TIMEOUT: ${{ secrets.TEST_TIMEOUT }}
50 |
51 | steps:
52 | - name: Checkout
53 | uses: actions/checkout@v2
54 |
55 | - uses: dorny/paths-filter@v2
56 | id: filter
57 | with:
58 | token: ${{ secrets.GITHUB_TOKEN }}
59 | filters: |
60 | go:
61 | - '**/*.go'
62 | - 'go.mod'
63 | - 'go.sum'
64 | - 'Makefile'
65 | - 'Dockerfile'
66 | - 'test/**/*'
67 |
68 | - name: Run e2e test
69 | id: run-e2e-test
70 | continue-on-error: true
71 | shell: bash
72 | if: steps.filter.outputs.go == 'true'
73 | run: |
74 | export RESULTS_DIR=/tmp/bfe-ingress-reports
75 | export CUCUMBER_OUTPUT_FORMAT=cucumber
76 | make e2e-test
77 |
78 | - name: Generate reports
79 | continue-on-error: true
80 | if: steps.filter.outputs.go == 'true'
81 | run: |
82 | # clone the gh-pages repository branch
83 | export TEMP_WORKTREE=$(mktemp -d)
84 | remote_repo="https://${GITHUB_ACTOR}:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git"
85 | git clone --branch=gh-pages --depth=1 "${remote_repo}" "${TEMP_WORKTREE}"
86 |
87 | export REPORTS_DIR=/tmp/bfe-ingress-reports
88 | export CONTROLLER_VERSION=$(cat VERSION)
89 | .github/generate-reports.sh
90 |
91 | - name: Upload cucumber json files
92 | uses: actions/upload-artifact@v2
93 | continue-on-error: true
94 | with:
95 | name: cucumber-output
96 | path: /tmp/bfe-ingress-reports/*
97 |
98 | - name: Check on failures
99 | if: steps.filter.outputs.go == 'true' && steps.run-e2e-test.outcome != 'success'
100 | run: exit 1
101 |
102 |
--------------------------------------------------------------------------------
/.github/workflows/helm.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | name: Helm
16 |
17 | on:
18 | push:
19 | branches:
20 | - main
21 |
22 | jobs:
23 |
24 | changes:
25 | runs-on: ubuntu-latest
26 | if: |
27 | (github.repository == 'bfenetworks/ingress-bfe')
28 | outputs:
29 | charts: ${{ steps.filter.outputs.charts }}
30 |
31 | steps:
32 |
33 | - name: Checkout
34 | uses: actions/checkout@v2
35 |
36 | - uses: dorny/paths-filter@v2
37 | id: filter
38 | with:
39 | token: ${{ secrets.GITHUB_TOKEN }}
40 | filters: |
41 | charts:
42 | - 'charts/bfe-ingress-controller/Chart.yaml'
43 | - 'charts/bfe-ingress-controller/**/*'
44 |
45 | chart:
46 | name: Release Chart
47 | runs-on: ubuntu-latest
48 | needs:
49 | - changes
50 | if: |
51 | (github.repository == 'bfenetworks/ingress-bfe') &&
52 | (needs.changes.outputs.charts == 'true')
53 |
54 | steps:
55 |
56 | - name: Checkout
57 | uses: actions/checkout@v2
58 | with:
59 | fetch-depth: 0
60 |
61 | - name: Configure Git
62 | shell: bash
63 | run: |
64 | git config --global user.name "$GITHUB_ACTOR"
65 | git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
66 |
67 | - name: Run chart-releaser
68 | uses: helm/chart-releaser-action@v1.1.0
69 | env:
70 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
71 | CR_RELEASE_NAME_TEMPLATE: "helm-chart-{{ .Version }}"
72 | with:
73 | charts_dir: charts
74 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # Binaries for programs and plugins
16 | *.exe
17 | *.exe~
18 | *.dll
19 | *.so
20 | *.dylib
21 |
22 | # Test binary, built with `go test -c`
23 | *.test
24 |
25 | # Output of the go coverage tool, specifically when used with LiteIDE
26 | *.out
27 |
28 | # Dependency directories (remove the comment below to include it)
29 | # vendor/
30 |
31 | # MacOS files
32 | .DS_Store
33 | */.DS_Store
34 |
35 | # .idea
36 | .idea
--------------------------------------------------------------------------------
/.licenserc.yaml:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 The BFE Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | header:
16 | license:
17 | spdx-id: Apache-2.0
18 | copyright-owner: The BFE Authors
19 |
20 | paths-ignore:
21 | - '.idea'
22 | - 'conf'
23 | - 'docs/images'
24 | - '**/go.mod'
25 | - '**/go.sum'
26 | - '**/*.md'
27 | - '**/*.orig'
28 | - 'examples/*'
29 | - 'LICENSE'
30 | - 'VERSION'
31 | - 'test/e2e/*'
32 |
33 | comment: on-failure
34 |
35 | dependency:
36 | files:
37 | - go.mod
38 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | repos:
16 | - repo: git://github.com/dnephin/pre-commit-golang
17 | rev: v0.4.0
18 | hooks:
19 | - id: go-fmt
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | ## v0.3.0 (2021-03-12)
6 |
7 | ### Enhancements:
8 | - Record k8s event for status change. [#47](https://github.com/bfenetworks/ingress-bfe/pull/47)
9 | - E2E test support. [#57](https://github.com/bfenetworks/ingress-bfe/pull/57), [#60](https://github.com/bfenetworks/ingress-bfe/pull/60)
10 | - Optimize startup logic. [#40](https://github.com/bfenetworks/ingress-bfe/pull/40), [#61](https://github.com/bfenetworks/ingress-bfe/pull/61)
11 | - Docs improvement. [#38](https://github.com/bfenetworks/ingress-bfe/pull/38), [#39](https://github.com/bfenetworks/ingress-bfe/pull/39), [#41](https://github.com/bfenetworks/ingress-bfe/pull/41), [#42](https://github.com/bfenetworks/ingress-bfe/pull/42), [#52](https://github.com/bfenetworks/ingress-bfe/pull/52), [#56](https://github.com/bfenetworks/ingress-bfe/pull/56), [#58](https://github.com/bfenetworks/ingress-bfe/pull/58), [#59](https://github.com/bfenetworks/ingress-bfe/pull/59)
12 | - License related. [#50](https://github.com/bfenetworks/ingress-bfe/pull/50), [#51](https://github.com/bfenetworks/ingress-bfe/pull/51)
13 |
14 |
15 |
16 | ## v0.2.2 (2021-11-17)
17 |
18 | ### Enhancements:
19 |
20 | - Docs improvement. [#28](https://github.com/bfenetworks/ingress-bfe/pull/28), [#29](https://github.com/bfenetworks/ingress-bfe/pull/29), [#33](https://github.com/bfenetworks/ingress-bfe/pull/33)
21 | - Helm Chart support. [#30](https://github.com/bfenetworks/ingress-bfe/pull/30)
22 | - Modify config files for deployment example. [#32](https://github.com/bfenetworks/ingress-bfe/pull/32)
23 |
24 | ### Fixes:
25 |
26 | - Fix license in some files. [#27](https://github.com/bfenetworks/ingress-bfe/pull/27)
27 |
28 | ## v0.2.1 (2021-10-27)
29 |
30 | ### Enhancements:
31 |
32 | - Document in English. [#22](https://github.com/bfenetworks/ingress-bfe/pull/22), [#25 ](https://github.com/bfenetworks/ingress-bfe/pull/25)
33 | - Support new argument for controller. [#19](https://github.com/bfenetworks/ingress-bfe/pull/19)
34 |
35 | ### Fixes:
36 |
37 | - service port checking. [#20](https://github.com/bfenetworks/ingress-bfe/pull/20)
38 |
39 | ## v0.2.0 (2021-10-15)
40 |
41 | ### Enhancements:
42 |
43 | - New version based on controller-runtime. [#11](https://github.com/bfenetworks/ingress-bfe/pull/11)
44 | - Document improvement. [#12](https://github.com/bfenetworks/ingress-bfe/pull/12), [#15](https://github.com/bfenetworks/ingress-bfe/pull/15)
45 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | FROM golang:1.16-alpine3.14 AS build
16 |
17 | RUN apk add build-base
18 |
19 | WORKDIR /bfe-ingress-controller
20 | COPY . .
21 | RUN build/build.sh
22 |
23 | FROM bfenetworks/bfe:v-1.3.0
24 | WORKDIR /
25 | COPY --from=build /bfe-ingress-controller/output/* /
26 |
27 | EXPOSE 8080 8443 8421
28 |
29 | ENTRYPOINT ["/bfe-ingress-controller"]
30 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2021 The BFE Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # init project path
16 | WORKROOT := $(shell pwd)
17 | OUTDIR := $(WORKROOT)/output
18 |
19 | # init environment variables
20 | export PATH := $(shell go env GOPATH)/bin:$(PATH)
21 | export GO111MODULE := on
22 |
23 | # init command params
24 | GO := go
25 | GOBUILD := $(GO) build
26 | GOTEST := $(GO) test
27 | GOVET := $(GO) vet
28 | GOGET := $(GO) get
29 | GOGEN := $(GO) generate
30 | GOCLEAN := $(GO) clean
31 | GOFLAGS := -race
32 | STATICCHECK := staticcheck
33 | LICENSEEYE := license-eye
34 |
35 | # init arch
36 | ARCH := $(shell getconf LONG_BIT)
37 | ifeq ($(ARCH),64)
38 | GOTEST += $(GOFLAGS)
39 | endif
40 |
41 | # init bfe ingress version
42 | INGRESS_VERSION ?= $(shell cat VERSION)
43 | # init git commit id
44 | GIT_COMMIT ?= $(shell git rev-parse HEAD)
45 |
46 | # init bfe ingress
47 | INGRESS_PACKAGES := $(shell go list ./...)
48 |
49 | # make, make all
50 | all: compile
51 |
52 | # make compile, go build
53 | compile: test build
54 | build:
55 | $(WORKROOT)/build/build.sh
56 |
57 | # make test, test your code
58 | test: test-case vet-case
59 | test-case:
60 | $(GOTEST) -cover ./...
61 | vet-case:
62 | ${GOVET} ./...
63 |
64 | # make coverage for codecov
65 | coverage:
66 | echo -n > coverage.txt
67 | for pkg in $(INGRESS_PACKAGES) ; do $(GOTEST) -coverprofile=profile.out -covermode=atomic $${pkg} && cat profile.out >> coverage.txt; done
68 |
69 | # make check
70 | check:
71 | $(GO) get honnef.co/go/tools/cmd/staticcheck
72 | $(STATICCHECK) ./...
73 |
74 | # make license-eye-install
75 | license-eye-install:
76 | $(GO) install github.com/apache/skywalking-eyes/cmd/license-eye@latest
77 |
78 | # make license-check, check code file's license declaration
79 | license-check: license-eye-install
80 | $(LICENSEEYE) header check
81 |
82 | # make license-fix, fix code file's license declaration
83 | license-fix: license-eye-install
84 | $(LICENSEEYE) header fix
85 |
86 | # make docker
87 | docker:
88 | docker build \
89 | -t bfenetworks/bfe-ingress-controller:$(INGRESS_VERSION) \
90 | -f Dockerfile \
91 | .
92 |
93 | # make clean
94 | clean:
95 | $(GOCLEAN)
96 | rm -rf $(OUTDIR)
97 |
98 | # e2e test
99 |
100 | kind-cluster:
101 | test/script/kind-create-cluster.sh
102 |
103 | test-env: docker kind-cluster
104 | test/script/kind-load-images.sh $(INGRESS_VERSION)
105 | test/script/deploy-controller.sh $(INGRESS_VERSION)
106 |
107 | e2e-test: test-env
108 | test/e2e/run.sh
109 | test/script/kind-delete-cluster.sh
110 |
111 | # avoid filename conflict and speed up build
112 | .PHONY: all compile test clean build docker e2e-test test-env kind-cluster
113 |
--------------------------------------------------------------------------------
/README-CN.md:
--------------------------------------------------------------------------------
1 | # BFE Ingress Controller
2 |
3 | 中文 | [English](README.md)
4 |
5 | [](https://goreportcard.com/report/github.com/bfenetworks/ingress-bfe)
6 |
7 | ## 简介
8 |
9 | BFE Ingress Controller 为基于 [BFE][] 实现的[Kubernetes Ingress Controller][],用于支持在 Kubernetes 中使用 [Ingress][] 进行流量接入,并利用BFE的众多优秀特点和强大能力。
10 |
11 | ## 特性和优势
12 |
13 | - 路由转发:支持基于Host、Path、Cookie、Header的路由规则
14 | - 多服务间负载均衡:支持在提供相同服务的多个Service之间进行负载均衡
15 | - 灵活的模块框架:采用灵活的模块框架设计,支持高效率定制开发扩展功能
16 | - 配置热加载:支持配置热加载,配置的更新和生效不会影响已存在的长连接
17 |
18 | ## 开始使用
19 |
20 | 详见[部署指南](docs/zh_cn/deployment.md)
21 |
22 | ## 说明文档
23 | 详见[文档列表](docs/zh_cn/SUMMARY.md)
24 |
25 | ## 参与贡献
26 | - 请首先在 [issue 列表](https://github.com/bfenetworks/ingress-bfe/issues) 中创建一个 issue
27 | - 如有必要,请联系项目维护者/负责人进行进一步讨论
28 | - 请遵循 [Golang 编程规范](https://github.com/golang/go/wiki/Style)
29 |
30 | ## 社区交流
31 |
32 | - [用户论坛](https://github.com/bfenetworks/ingress-bfe/discussions)
33 |
34 | - **开源BFE微信公众号**:扫码关注公众号“BFE开源项目”,及时获取项目最新信息和技术分享
35 |
36 |
37 |
38 |  |
39 |
40 |
41 |
42 | - **开源BFE用户微信群**:扫码加入,探讨和分享对BFE的建议、使用心得、疑问等
43 |
44 |
45 |
46 |  |
47 |
48 |
49 |
50 | - **开源BFE开发者微信群**: [发送邮件](mailto:iyangsj@gmail.com)说明您的微信号及贡献(例如PR/Issue),我们将及时邀请您加入
51 |
52 | ## 许可
53 | 基于 Apache 2.0 许可证,详见 [LICENSE](https://github.com/bfenetworks/ingress-bfe/blob/master/LICENSE) 文件说明
54 |
55 | [Kubernetes Ingress Controller]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/ "Kubernetes"
56 | [Ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/ "Kubernetes"
57 | [BFE]: https://github.com/bfenetworks/bfe "Github"
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BFE Ingress Controller
2 |
3 | English | [中文](README-CN.md)
4 |
5 | [](https://goreportcard.com/report/github.com/bfenetworks/ingress-bfe)
6 |
7 | ## Overview
8 |
9 | BFE Ingress Controller is an implementation of Kubernetes [Ingress Controller][] based on [BFE][], to fulfill [Ingress][] in Kubernetes.
10 |
11 | ## Features and Advantages
12 |
13 | - Traffic routing based on Host, Path, Cookie and Header
14 | - Support for load balancing among multiple Services of the same application
15 | - Flexible plugin framework, based on which developers can add new features efficiently
16 | - Configuration hot reload, avoiding impact on existing long connections
17 |
18 | ## Quick start
19 |
20 | See [Deployment](docs/en_us/deployment.md) for quick start of using BFE Ingress Controller.
21 |
22 | ## Documentation
23 | See [Document Summary](docs/en_us/SUMMARY.md).
24 |
25 | ## Contributing
26 | - Create and issue in [Issue List](https://github.com/bfenetworks/ingress-bfe/issues)
27 | - If necessary, contact and discuss with maintainer
28 | - Follow the [Golang style guide](https://github.com/golang/go/wiki/Style)
29 |
30 | ## Communication
31 |
32 | - [Forum](https://github.com/bfenetworks/ingress-bfe/discussions)
33 | - BFE community on Slack: [Sign up](https://slack.cncf.io/) CNCF Slack and join bfe channel.
34 | - BFE developer group on WeChat: [Send a request mail](mailto:iyangsj@gmail.com) with your WeChat ID and a contribution you've made to BFE(such as a PR/Issue). We will invite you right away.
35 |
36 | ## License
37 |
38 | BFE is under the Apache 2.0 license. See the [LICENSE](https://github.com/bfenetworks/ingress-bfe/blob/master/LICENSE) file for details
39 |
40 | [Ingress Controller]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/ "Kubernetes"
41 | [Ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/ "Kubernetes"
42 | [BFE]: https://github.com/bfenetworks/bfe "Github"
43 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 |
5 | Please do not open issues for anything you think might have a security implication.
6 |
7 | Security issues and bugs should be reported privately to .
8 | You should receive a response within 24 hours. If for some reason you do not,
9 | please follow up via email to ensure we received your original message.
10 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 0.3.0-dev
2 |
--------------------------------------------------------------------------------
/build/build.sh:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | set -e
16 | set -x
17 |
18 | WORK_ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
19 |
20 | # init version
21 | VERSION=$(cat $WORK_ROOT/VERSION)
22 | # init git commit id
23 | GIT_COMMIT=$(git rev-parse HEAD) || true
24 |
25 | go build -ldflags "-X main.version=${VERSION} -X main.commit=${GIT_COMMIT}" \
26 | -o $WORK_ROOT/output/bfe-ingress-controller $WORK_ROOT/cmd/ingress-controller
27 |
28 | # set permission for docker
29 | cp $WORK_ROOT/scripts/* $WORK_ROOT/output/
30 | chmod a+x $WORK_ROOT/output/*
31 | echo "${GIT_COMMIT}" > $WORK_ROOT/output/ingress.commit
32 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/.helmignore:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # Patterns to ignore when building packages.
16 | # This supports shell glob matching, relative path matching, and
17 | # negation (prefixed with !). Only one pattern per line.
18 | .DS_Store
19 | # Common VCS dirs
20 | .git/
21 | .gitignore
22 | .bzr/
23 | .bzrignore
24 | .hg/
25 | .hgignore
26 | .svn/
27 | # Common backup files
28 | *.swp
29 | *.bak
30 | *.tmp
31 | *.orig
32 | *~
33 | # Various IDEs
34 | .project
35 | .idea/
36 | *.tmproj
37 | .vscode/
38 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/Chart.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | apiVersion: v2
16 | name: bfe-ingress-controller
17 | description: Helm chart for BFE Ingress Controller
18 | type: application
19 | version: 0.1.0
20 | appVersion: "0.2.2"
21 | keywords:
22 | - ingress
23 | - bfe
24 | home: https://github.com/bfenetworks/ingress-bfe
25 | icon: https://landscape.cncf.io/logos/bfe.svg
26 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | 1. Get the application URL by running these commands:
2 | {{- if contains "NodePort" .Values.service.type }}
3 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "bfe-ingress-controller.fullname" . }})
4 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
5 | echo http://$NODE_IP:$NODE_PORT
6 | {{- else if contains "LoadBalancer" .Values.service.type }}
7 | NOTE: It may take a few minutes for the LoadBalancer IP to be available.
8 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "bfe-ingress-controller.fullname" . }}'
9 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "bfe-ingress-controller.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
10 | echo http://$SERVICE_IP:{{ .Values.containerPort.http }}
11 | {{- else if contains "ClusterIP" .Values.service.type }}
12 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "bfe-ingress-controller.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
13 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
14 | echo "Visit http://127.0.0.1:8080 to use your application"
15 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
16 | {{- end }}
17 |
18 | 2. Test HTTP port, return 500
19 | curl -v $(echo http://$NODE_IP:$NODE_PORT)
20 |
21 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/_helpers.tpl:
--------------------------------------------------------------------------------
1 | {*
2 | Copyright 2022 The BFE Authors
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
16 | *}
17 | {{/*
18 | Expand the name of the chart.
19 | */}}
20 | {{- define "bfe-ingress-controller.name" -}}
21 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
22 | {{- end }}
23 |
24 | {{/*
25 | Create a default fully qualified app name.
26 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
27 | If release name contains chart name it will be used as a full name.
28 | */}}
29 | {{- define "bfe-ingress-controller.fullname" -}}
30 | {{- if .Values.fullnameOverride }}
31 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
32 | {{- else }}
33 | {{- $name := default .Chart.Name .Values.nameOverride }}
34 | {{- if contains $name .Release.Name }}
35 | {{- .Release.Name | trunc 63 | trimSuffix "-" }}
36 | {{- else }}
37 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
38 | {{- end }}
39 | {{- end }}
40 | {{- end }}
41 |
42 | {{/*
43 | Create chart name and version as used by the chart label.
44 | */}}
45 | {{- define "bfe-ingress-controller.chart" -}}
46 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
47 | {{- end }}
48 |
49 | {{/*
50 | Common labels
51 | */}}
52 | {{- define "bfe-ingress-controller.labels" -}}
53 | helm.sh/chart: {{ include "bfe-ingress-controller.chart" . }}
54 | {{ include "bfe-ingress-controller.selectorLabels" . }}
55 | {{- if .Chart.AppVersion }}
56 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
57 | {{- end }}
58 | app.kubernetes.io/managed-by: {{ .Release.Service }}
59 | {{- end }}
60 |
61 | {{/*
62 | Selector labels
63 | */}}
64 | {{- define "bfe-ingress-controller.selectorLabels" -}}
65 | app.kubernetes.io/name: {{ include "bfe-ingress-controller.name" . }}
66 | app.kubernetes.io/instance: {{ .Release.Name }}
67 | {{- end }}
68 |
69 | {{/*
70 | Create the name of the service account to use
71 | */}}
72 | {{- define "bfe-ingress-controller.serviceAccountName" -}}
73 | {{- if .Values.serviceAccount.create }}
74 | {{- default (include "bfe-ingress-controller.fullname" .) .Values.serviceAccount.name }}
75 | {{- else }}
76 | {{- default "default" .Values.serviceAccount.name }}
77 | {{- end }}
78 | {{- end }}
79 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/deployment.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | apiVersion: apps/v1
16 | kind: Deployment
17 | metadata:
18 | name: {{ include "bfe-ingress-controller.fullname" . }}
19 | labels:
20 | {{- include "bfe-ingress-controller.labels" . | nindent 4 }}
21 | spec:
22 | {{- if not .Values.autoscaling.enabled }}
23 | replicas: {{ .Values.replicaCount }}
24 | {{- end }}
25 | selector:
26 | matchLabels:
27 | {{- include "bfe-ingress-controller.selectorLabels" . | nindent 6 }}
28 | template:
29 | metadata:
30 | {{- with .Values.podAnnotations }}
31 | annotations:
32 | {{- toYaml . | nindent 8 }}
33 | {{- end }}
34 | labels:
35 | {{- include "bfe-ingress-controller.selectorLabels" . | nindent 8 }}
36 | spec:
37 | {{- with .Values.imagePullSecrets }}
38 | imagePullSecrets:
39 | {{- toYaml . | nindent 8 }}
40 | {{- end }}
41 | serviceAccountName: {{ include "bfe-ingress-controller.serviceAccountName" . }}
42 | securityContext:
43 | {{- toYaml .Values.podSecurityContext | nindent 8 }}
44 | containers:
45 | - name: {{ .Chart.Name }}
46 | securityContext:
47 | {{- toYaml .Values.securityContext | nindent 12 }}
48 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
49 | imagePullPolicy: {{ .Values.image.pullPolicy }}
50 | args:
51 | {{- if .Values.scope.namespaces }}
52 | - "-n"
53 | - {{ .Values.scope.namespaces | quote}}
54 | {{- end }}
55 | ports:
56 | {{- range $key, $value := .Values.containerPort }}
57 | - name: {{ $key }}
58 | containerPort: {{ $value }}
59 | protocol: TCP
60 | {{- end }}
61 | livenessProbe: {{ toYaml .Values.livenessProbe | nindent 12 }}
62 | readinessProbe: {{ toYaml .Values.readinessProbe | nindent 12 }}
63 | resources:
64 | {{- toYaml .Values.resources | nindent 12 }}
65 | {{- with .Values.nodeSelector }}
66 | nodeSelector:
67 | {{- toYaml . | nindent 8 }}
68 | {{- end }}
69 | {{- with .Values.affinity }}
70 | affinity:
71 | {{- toYaml . | nindent 8 }}
72 | {{- end }}
73 | {{- with .Values.tolerations }}
74 | tolerations:
75 | {{- toYaml . | nindent 8 }}
76 | {{- end }}
77 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/hpa.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | {{- if .Values.autoscaling.enabled }}
16 | apiVersion: autoscaling/v2beta1
17 | kind: HorizontalPodAutoscaler
18 | metadata:
19 | name: {{ include "bfe-ingress-controller.fullname" . }}
20 | labels:
21 | {{- include "bfe-ingress-controller.labels" . | nindent 4 }}
22 | spec:
23 | scaleTargetRef:
24 | apiVersion: apps/v1
25 | kind: Deployment
26 | name: {{ include "bfe-ingress-controller.fullname" . }}
27 | minReplicas: {{ .Values.autoscaling.minReplicas }}
28 | maxReplicas: {{ .Values.autoscaling.maxReplicas }}
29 | metrics:
30 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
31 | - type: Resource
32 | resource:
33 | name: cpu
34 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
35 | {{- end }}
36 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
37 | - type: Resource
38 | resource:
39 | name: memory
40 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
41 | {{- end }}
42 | {{- end }}
43 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/rbac.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | {{- if .Values.rbac.create }}
16 |
17 | apiVersion: rbac.authorization.k8s.io/v1
18 | kind: ClusterRole
19 | metadata:
20 | labels:
21 | {{- include "bfe-ingress-controller.labels" . | nindent 4 }}
22 | name: {{ include "bfe-ingress-controller.fullname" . }}
23 | rules:
24 | - apiGroups:
25 | - ""
26 | resources:
27 | - endpoints
28 | - services
29 | - secrets
30 | - namespaces
31 | - nodes
32 | verbs:
33 | - get
34 | - list
35 | - watch
36 | - apiGroups:
37 | - ""
38 | resources:
39 | - events
40 | verbs:
41 | - create
42 | - patch
43 | - apiGroups:
44 | - extensions
45 | - networking.k8s.io
46 | resources:
47 | - ingresses
48 | verbs:
49 | - get
50 | - list
51 | - watch
52 | - update
53 | - patch
54 | - apiGroups:
55 | - ""
56 | resources:
57 | - events
58 | verbs:
59 | - create
60 | - patch
61 | - update
62 | - apiGroups:
63 | - networking.k8s.io
64 | resources:
65 | - ingresses/status
66 | verbs:
67 | - update
68 | - patch
69 | - apiGroups:
70 | - networking.k8s.io
71 | resources:
72 | - ingressclasses
73 | verbs:
74 | - get
75 | - list
76 | - watch
77 |
78 | ---
79 | apiVersion: rbac.authorization.k8s.io/v1
80 | kind: ClusterRoleBinding
81 | metadata:
82 | labels:
83 | {{- include "bfe-ingress-controller.labels" . | nindent 4 }}
84 | name: {{ include "bfe-ingress-controller.fullname" . }}
85 | roleRef:
86 | apiGroup: rbac.authorization.k8s.io
87 | kind: ClusterRole
88 | name: {{ include "bfe-ingress-controller.fullname" . }}
89 | subjects:
90 | - kind: ServiceAccount
91 | name: {{ template "bfe-ingress-controller.serviceAccountName" . }}
92 | namespace: {{ .Release.Namespace | quote }}
93 |
94 | {{- end }}
95 |
96 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/service.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | apiVersion: v1
16 | kind: Service
17 | metadata:
18 | name: {{ include "bfe-ingress-controller.fullname" . }}
19 | labels:
20 | {{- include "bfe-ingress-controller.labels" . | nindent 4 }}
21 | spec:
22 | type: {{ .Values.service.type }}
23 | ports:
24 | {{- range $key, $value := .Values.containerPort }}
25 | - name: {{ $key }}
26 | port: {{ $value }}
27 | targetPort: {{ $value }}
28 | {{- end }}
29 | selector:
30 | {{- include "bfe-ingress-controller.selectorLabels" . | nindent 4 }}
31 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/templates/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | {{- if .Values.serviceAccount.create }}
16 | apiVersion: v1
17 | kind: ServiceAccount
18 | metadata:
19 | name: {{ include "bfe-ingress-controller.serviceAccountName" . }}
20 | labels:
21 | {{- include "bfe-ingress-controller.labels" . | nindent 4 }}
22 | {{- with .Values.serviceAccount.annotations }}
23 | annotations:
24 | {{- toYaml . | nindent 4 }}
25 | {{- end }}
26 | {{- end }}
27 |
--------------------------------------------------------------------------------
/charts/bfe-ingress-controller/values.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 The BFE Authors
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # Default values for bfe-ingress-controller.
16 | replicaCount: 1
17 |
18 | image:
19 | repository: bfenetworks/bfe-ingress-controller
20 | pullPolicy: IfNotPresent
21 | # Overrides the image tag whose default is the chart appVersion.
22 | tag: ""
23 |
24 | imagePullSecrets: []
25 | nameOverride: ""
26 | fullnameOverride: ""
27 |
28 | containerPort:
29 | http: 8080
30 | https: 8443
31 | monitor: 8421
32 |
33 | livenessProbe:
34 | httpGet:
35 | path: "/"
36 | port: 8421
37 | scheme: HTTP
38 | initialDelaySeconds: 5
39 | periodSeconds: 5
40 | timeoutSeconds: 1
41 | successThreshold: 1
42 | failureThreshold: 5
43 |
44 | readinessProbe:
45 | httpGet:
46 | path: "/"
47 | port: 8421
48 | scheme: HTTP
49 | initialDelaySeconds: 10
50 | periodSeconds: 5
51 | timeoutSeconds: 1
52 | successThreshold: 1
53 | failureThreshold: 3
54 |
55 | serviceAccount:
56 | # Specifies whether a service account should be created
57 | create: true
58 | # Annotations to add to the service account
59 | annotations: {}
60 | # The name of the service account to use.
61 | # If not set and create is true, a name is generated using the fullname template
62 | name: ""
63 |
64 | podAnnotations: {}
65 |
66 | podSecurityContext: {}
67 | # fsGroup: 2000
68 |
69 | securityContext: {}
70 | # capabilities:
71 | # drop:
72 | # - ALL
73 | # readOnlyRootFilesystem: true
74 | # runAsNonRoot: true
75 | # runAsUser: 1000
76 |
77 | service:
78 | type: NodePort
79 |
80 | scope: {}
81 | # Set namespaces the controller watch, delimited by ','
82 | # Default to all namespace
83 | # namespaces: namespace1,namespace2
84 |
85 | resources: {}
86 | # We usually recommend not to specify default resources and to leave this as a conscious
87 | # choice for the user. This also increases chances charts run on environments with little
88 | # resources, such as Minikube. If you do want to specify resources, uncomment the following
89 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
90 | # limits:
91 | # cpu: 100m
92 | # memory: 128Mi
93 | # requests:
94 | # cpu: 100m
95 | # memory: 128Mi
96 |
97 | autoscaling:
98 | enabled: false
99 | minReplicas: 1
100 | maxReplicas: 100
101 | targetCPUUtilizationPercentage: 80
102 | # targetMemoryUtilizationPercentage: 80
103 |
104 | nodeSelector: {}
105 |
106 | tolerations: []
107 |
108 | affinity: {}
109 |
110 | rbac:
111 | create: true
112 |
--------------------------------------------------------------------------------
/cmd/ingress-controller/flags.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | "flag"
19 |
20 | "github.com/bfenetworks/ingress-bfe/internal/option"
21 | )
22 |
23 | var (
24 | help bool
25 | showVersion bool
26 |
27 | opts *option.Options = option.NewOptions()
28 | )
29 |
30 | func initFlags() {
31 | flag.BoolVar(&help, "help", false, "Show help.")
32 | flag.BoolVar(&help, "h", false, "Show help.")
33 |
34 | flag.BoolVar(&showVersion, "version", false, "Show version of bfe-ingress-controller.")
35 | flag.BoolVar(&showVersion, "v", false, "Show version of bfe-ingress-controller.")
36 |
37 | flag.StringVar(&opts.Namespaces, "namespace", opts.Namespaces, "Namespaces to watch, delimited by ','.")
38 | flag.StringVar(&opts.Namespaces, "n", opts.Namespaces, "Namespaces to watch, delimited by ','.")
39 |
40 | flag.StringVar(&opts.MetricsAddr, "metrics-bind-address", opts.MetricsAddr, "The address the metric endpoint binds to.")
41 | flag.StringVar(&opts.HealthProbeAddr, "health-probe-bind-address", opts.HealthProbeAddr, "The address the probe endpoint binds to.")
42 | flag.StringVar(&opts.ClusterName, "k8s-cluster-name", opts.ClusterName, "k8s cluster name")
43 |
44 | flag.StringVar(&opts.Ingress.ConfigPath, "bfe-config-path", opts.Ingress.ConfigPath, "Root directory of bfe configuration files.")
45 | flag.StringVar(&opts.Ingress.ConfigPath, "c", opts.Ingress.ConfigPath, "Root directory of bfe configuration files.")
46 | flag.StringVar(&opts.Ingress.BfeBinary, "bfe-binary", opts.Ingress.BfeBinary, "Absolute path of BFE binary. If set, is overwritten by /../conf")
47 | flag.StringVar(&opts.Ingress.BfeBinary, "b", opts.Ingress.BfeBinary, "Absolute path of BFE binary. If set, is overwritten by /../conf,")
48 | flag.StringVar(&opts.Ingress.ReloadAddr, "bfe-reload-address", opts.Ingress.ReloadAddr, "Address of bfe config reloading.")
49 | flag.StringVar(&opts.Ingress.IngressClass, "ingress-class", opts.Ingress.IngressClass, "Class name of bfe ingress controller.")
50 | flag.StringVar(&opts.Ingress.DefaultBackend, "default-backend", opts.Ingress.DefaultBackend, "set default backend name, default backend is used if no any ingress rule matched, format namespace/name.")
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/cmd/ingress-controller/main.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | "flag"
19 | "fmt"
20 | rt "runtime"
21 |
22 | "k8s.io/apimachinery/pkg/runtime"
23 | utilruntime "k8s.io/apimachinery/pkg/util/runtime"
24 | clientgoscheme "k8s.io/client-go/kubernetes/scheme"
25 | ctrl "sigs.k8s.io/controller-runtime"
26 | "sigs.k8s.io/controller-runtime/pkg/log/zap"
27 |
28 | "github.com/bfenetworks/ingress-bfe/internal/controllers"
29 | "github.com/bfenetworks/ingress-bfe/internal/option"
30 | )
31 |
32 | var (
33 | scheme = runtime.NewScheme()
34 | setupLog = ctrl.Log.WithName("setup")
35 | )
36 |
37 | func init() {
38 | utilruntime.Must(clientgoscheme.AddToScheme(scheme))
39 | initFlags()
40 | }
41 |
42 | var (
43 | version string
44 | commit string
45 | )
46 |
47 | func main() {
48 | zapOpts := zap.Options{
49 | Development: true,
50 | }
51 | zapOpts.BindFlags(flag.CommandLine)
52 | flag.Parse()
53 | ctrl.SetLogger(zap.New(zap.UseFlagOptions(&zapOpts)))
54 |
55 | if help {
56 | flag.PrintDefaults()
57 | return
58 | }
59 | if showVersion {
60 | fmt.Printf("bfe-ingress-controller version: %s\n", version)
61 | fmt.Printf("go version: %s\n", rt.Version())
62 | fmt.Printf("git commit: %s\n", commit)
63 | return
64 | }
65 |
66 | err := option.SetOptions(opts)
67 | if err != nil {
68 | setupLog.Error(err, "fail to start controllers")
69 | return
70 | }
71 |
72 | setupLog.Info("starting bfe-ingress-controller")
73 |
74 | if err := controllers.Start(scheme); err != nil {
75 | setupLog.Error(err, "fail to start controllers")
76 | }
77 |
78 | setupLog.Info("bfe-ingress-controller exit")
79 | }
80 |
--------------------------------------------------------------------------------
/dist/bfe.ini:
--------------------------------------------------------------------------------
1 | ; Copyright 2021 The BFE Authors
2 | ;
3 | ; Licensed under the Apache License, Version 2.0 (the "License");
4 | ; you may not use this file except in compliance with the License.
5 | ; You may obtain a copy of the License at
6 | ;
7 | ; http://www.apache.org/licenses/LICENSE-2.0
8 | ;
9 | ; Unless required by applicable law or agreed to in writing, software
10 | ; distributed under the License is distributed on an "AS IS" BASIS,
11 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | ; See the License for the specific language governing permissions and
13 | ; limitations under the License.
14 | ;
15 | [program:bfe]
16 | directory=/home/work/bfe/bin/
17 | command=./bfe -c ../conf -l ../log -d
18 | priority=999 ; the relative start priority (default 999)
19 | autostart=true ; start at supervisord start (default: true)
20 | autorestart=true ; retstart at unexpected quit (default: true)
21 | startsecs=10 ; number of secs prog must stay running (def. 10)
22 | startretries=3 ; max # of serial start failures (default 3)
23 | exitcodes=0,2 ; 'expected' exit codes for process (default 0,2)
24 | stopsignal=QUIT ; signal used to kill process (default TERM)
25 | stopwaitsecs=10 ; max num secs to wait before SIGKILL (default 10)
26 | user=work ; setuid to this UNIX account to run the program
27 | log_stdout=true
28 | log_stderr=true ; if true, log program stderr (def false)
29 | logfile=/tmp/echo_time.log
30 | logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB)
31 | logfile_backups=10 ; # of logfile backups (default 10)
32 | stdout_logfile_maxbytes=20MB ; stdout file size,default 50MB
33 | stdout_logfile_backups=2 ; stdout file number
34 | stdout_logfile=/tmp/echo_time.stdout.log
35 |
--------------------------------------------------------------------------------
/dist/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2021 The BFE Authors
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | set -x
17 |
18 | readonly BFE_BIN=bfe
19 |
20 | cd /home/work/bfe/bin/ && nohup ./${BFE_BIN} -c ../conf -l ../log -d &
21 |
22 | if [ -n "$INGRESS_LISTEN_NAMESPACE" ]; then
23 | cd /home/work/bfe/bin/ && ./bfe_ingress_controller -l ../log -c "/home/work/bfe/conf/" -n "$INGRESS_LISTEN_NAMESPACE" "$@"
24 | else
25 | cd /home/work/bfe/bin/ && ./bfe_ingress_controller -l ../log -c "/home/work/bfe/conf/" "$@"
26 | fi
--------------------------------------------------------------------------------
/docs/en_us/FAQ/FAQ.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 | 1. Question:what arguments can be used to run BFE Ingress Controller, and how to define them?
3 |
4 | Answer: Arguments supported by BFE Ingress Controller:
5 |
6 | |Argument | Default value | Description|
7 | | --- | --- | --- |
8 | | --namespace
-n | Empty String | Specify in which namespaces BFE Ingress Controller will monitor Ingress. Multiple namespaces are seperated by `,`.
Default value is empty string which means to monitor all namespaces. |
9 | | --ingress-class| bfe | Specify the `kubernetes.io/ingress.class` value of Ingress it monitors.
If not specified, BFE Ingress Controller monitors the Ingress with ingress class set as "bfe". Usually you don't need to specify it. |
10 | | --default-backend| Empty String | Specify name of default backend service, in the format of `namespace/name`.
If specified, requests that match no Ingress rule will be forwarded to the service specified. |
11 |
12 | How to define:
13 | Define in config file of BFE Ingress Controller, like [controller.yaml](../../../examples/controller.yaml). Example:
14 |
15 | ```yaml
16 | ...
17 | containers:
18 | - name: bfe-ingress-controller
19 | image: bfenetworks/bfe-ingress-controller:latest
20 | args: ["-n", "ns1,ns2", "--default-backend", "test/whoami"]
21 | ...
22 | ```
23 |
--------------------------------------------------------------------------------
/docs/en_us/README.md:
--------------------------------------------------------------------------------
1 | # BFE Ingress Controller
2 |
3 | BFE Ingress Controller is a Kubernetes [Ingress Controller][] based on [BFE][], to fulfill the [Ingress][] in Kubernetes.
4 |
5 | [Documents](SUMMARY.md)
6 |
7 | [Ingress Controller]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/ "Kubernetes"
8 | [Ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/ "Kubernetes"
9 | [BFE]: https://github.com/bfenetworks/bfe "Github"
10 |
11 |
--------------------------------------------------------------------------------
/docs/en_us/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | [comment]: <> "For user"
4 | * Deployment
5 | * [Deployment Guide](deployment.md)
6 | * [Role-Based Access Control (RBAC)](rbac.md)
7 | * Configuration
8 | * [Configuration Guide](ingress/basic.md)
9 | * [Ingress Status](ingress/validate-state.md)
10 | * [Priority of Route Rules](ingress/priority.md)
11 | * [Principles of Handling Route Rule Conflicts](ingress/conflict.md)
12 | * [TLS Configuration](ingress/tls.md)
13 | * [Load Balance](ingress/load-balance.md)
14 | * [Redirect](ingress/redirect.md)
15 | * [Rewrite](ingress/rewrite.md)
16 | * Configuration Examples
17 | * [Config File Example](example/example.md)
18 | * [Canary Release Example](example/canary-release.md)
19 | * [FAQ](FAQ/FAQ.md)
20 | * Appendix
21 | * [Annotations](appendix/annotations.md)
22 |
23 | ---
24 |
25 | [comment]: <> "For developer"
26 | * [How to contribute](contribute/how-to-contribute.md)
27 | * [Contribute codes](contribute/contribute-codes.md)
28 | * [Contribute documents](contribute/contribute-documents.md)
29 | * [Release Regulation](https://www.bfe-networks.net/en_us/development/release_regulation/)
30 |
31 |
--------------------------------------------------------------------------------
/docs/en_us/contribute/contribute-documents.md:
--------------------------------------------------------------------------------
1 | # Contribute Document
2 |
3 | ## Requirement
4 | - All documents should be written in [Markdown][markdown] (GitHub style),using filename with suffix `.md`
5 | - If new document is created, add its link in the index file([SUMMARY.md](../SUMMARY.md))
6 | ## Process
7 |
8 | 1. Create or edit document
9 | 2. Use preview tools to preview and modify if necessary
10 | - [How to use preview tool](https://www.bfe-networks.net/en_us/development/write_doc_guide/#_2)
11 | 3. Submit
12 | - Commit and initiate a Pull Request, refer to [Contribute Code](contribute-codes.md)
13 |
14 | > Refer to [Contribute Documentation](https://www.bfe-networks.net/en_us/development/write_doc_guide/) of BFE
15 |
16 | [markdown]: https://guides.github.com/features/mastering-markdown/
17 |
18 |
--------------------------------------------------------------------------------
/docs/en_us/contribute/how-to-contribute.md:
--------------------------------------------------------------------------------
1 | # Contribute
2 | - [Contribute Code](contribute-codes.md)
3 | - [Contribute Document](contribute-documents.md)
4 | - [Release Regulation](https://www.bfe-networks.net/en_us/development/release_regulation/)
5 |
6 |
--------------------------------------------------------------------------------
/docs/en_us/deployment.md:
--------------------------------------------------------------------------------
1 | # Deployment Guide
2 |
3 | ## Installation
4 | Install BFE Ingress Controller in either of two ways:
5 | * Apply a configure file
6 | * Install helm charts of controller
7 |
8 | ### Configure file
9 |
10 | ``` shell script
11 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/controller-all.yaml
12 | ```
13 |
14 | - Above configure file uses the latest version of [BFE Ingress Controller image](https://hub.docker.com/r/bfenetworks/bfe-ingress-controller) in Docker Hub. You can edit configure file to specify other version of the image.
15 |
16 | - For details of permission configuration, please find more information in [Role-Based Access Control](rbac.md)
17 |
18 | ### Helm
19 |
20 | ```
21 | helm upgrade --install bfe-ingress-controller bfe-ingress-controller --repo https://bfenetworks.github.io/ingress-bfe --namespace ingress-bfe --create-namespace
22 | ```
23 |
24 | - helm3 is required.
25 |
26 | ## Testing
27 |
28 | * Create a testing service
29 |
30 | ``` shell script
31 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/whoami.yaml
32 | ```
33 |
34 | * Create ingress resource for testing service to verify the installation
35 |
36 | ``` shell script
37 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/ingress.yaml
38 |
39 | ```
40 |
41 | * Create ingress resource for testing service to verify the installation if your kubernetes version >= 1.19
42 | ``` shell script
43 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/ingress-v1.19.yaml
44 |
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/en_us/example/canary-release.md:
--------------------------------------------------------------------------------
1 | # Canary Release
2 |
3 | ## Introduction
4 | BFE Ingress Controller supports `Header/Cookie` based "canary release" by configuring`Annotation`.
5 |
6 | ## Config Example
7 | * Original ingress configuration is shown as follows. Ingress will forward matched requests to `service`:
8 | ```yaml
9 | kind: Ingress
10 | apiVersion: networking.k8s.io/v1beta1
11 | metadata:
12 | name: "original"
13 | namespace: production
14 |
15 | spec:
16 | rules:
17 | - host: example.net
18 | http:
19 | paths:
20 | - path: /bar
21 | pathType: Exact
22 | backend:
23 | serviceName: service
24 | servicePort: 80
25 | ```
26 |
27 | * Canary release is applied and interested requests should be forwarded to a new service `service2`.
28 | * To achieve this, create a new ingress, with header or cookie information of interested requests included in annotations.
29 | ```yaml
30 | kind: Ingress
31 | apiVersion: networking.k8s.io/v1beta1
32 | metadata:
33 | name: "greyscale"
34 | namespace: production
35 | annotations:
36 | bfe.ingress.kubernetes.io/router.cookie: "key: value"
37 | bfe.ingress.kubernetes.io/router.header: "Key: Value"
38 |
39 | spec:
40 | rules:
41 | - host: example.net
42 | http:
43 | paths:
44 | - path: /bar
45 | pathType: Exact
46 | backend:
47 | serviceName: service2
48 | servicePort: 80
49 |
50 | ```
51 | * Based on above configuration, BFE Ingress Controller will
52 | 1. forward requests with `host == example.net && path == /bar && cookie[key] == value && Header[Key] == Value`
53 | to service `service-new`
54 | 1. forward other requests with `host == example.net && path == /bar`
55 | to service `service`
56 |
--------------------------------------------------------------------------------
/docs/en_us/example/example.md:
--------------------------------------------------------------------------------
1 | # Examples of Config File
2 |
3 | ## deployment
4 | | Program | File | Description |
5 | | ---- | ---- | ---- |
6 | | bfe-ingress-controller | [controller.yaml](../../../examples/controller.yaml)| to deploy BFE Ingress Controller |
7 | | example backend service: whoami | [whoami.yaml](../../../examples/whoami.yaml) | to deploy example service `whoami` |
8 |
9 | ## ingress
10 | | File | Description |
11 | | ---- | ---- |
12 | | [ingress.yaml](../../../examples/ingress.yaml) | to config route for traffic to example service `whoami` |
13 |
14 | ## rbac
15 | | File | Description |
16 | | ---- | ---- |
17 | | [rbac.yaml](../../../examples/rbac.yaml) | to config access control for BFE Ingress Controller |
18 |
19 |
--------------------------------------------------------------------------------
/docs/en_us/ingress/conflict.md:
--------------------------------------------------------------------------------
1 | # Route Rule Conflict
2 |
3 | ## Definition
4 | If Ingress configurations create Ingress resources containing at least one identical Ingress rule (host, path and advanced conditions are all the same), a route rule conflict happens.
5 |
6 | ## Conflict handling: first-created-resource-win principle
7 |
8 | For those Ingress resources with route rule conflict, BFE Ingress Controller will follow first-created-resource-win principle and only takes the first created Ingress resource as valid.
9 |
10 | This principle will be followed when route rule conflict happens within a namespace or across different namespaces.
11 |
12 | For those invalid Ingress resources due to route rule conflict, error messages will be written to its annotation, see [Ingress Status](validate-state.md).
13 |
14 | ## Example
15 |
16 | ```yaml
17 | apiVersion: networking.k8s.io/v1beta1
18 | kind: Ingress
19 | metadata:
20 | name: ingress-A
21 | namespace: production
22 | annotations:
23 | kubernetes.io/ingress.class: bfe
24 | spec:
25 | rules:
26 | - host: example.foo.com
27 | http:
28 | paths:
29 | - path: /foo
30 | pathType: Prefix
31 | backend:
32 | serviceName: service1
33 | servicePort: 80
34 | ---
35 | apiVersion: networking.k8s.io/v1beta1
36 | kind: Ingress
37 | metadata:
38 | name: ingress-B
39 | namespace: production
40 | annotations:
41 | kubernetes.io/ingress.class: bfe
42 | spec:
43 | rules:
44 | - host: example.foo.com
45 | http:
46 | paths:
47 | - path: /foo
48 | pathType: Prefix
49 | backend:
50 | serviceName: service2
51 | servicePort: 80
52 |
53 | ```
54 | In above configuration, there is conflict between ingress-A and ingress-B, and ingress-A is created before ingress-B. So only ingress-A will be created and take effect.
55 |
56 | ## Ingress status feedback
57 | If an Ingress resource is invalid due to route rule conflict, after the ingress status is written back, the `status` in `annotation` will be set as “fail”, and `message` will tell which Ingress resource it has conflict with.
58 |
59 | In previous example, `annotation` for ingress status will be like:
60 |
61 |
62 | ```yaml
63 | metadata:
64 | annotations:
65 | bfe.ingress.kubernetes.io/bfe-ingress-status: |
66 | {"status": "fail", "message": "conflict with production/ingress-A"}
67 | ```
68 |
69 | For more information about ingress status, refer to [ingress status](validate-state.md)。
70 |
71 |
--------------------------------------------------------------------------------
/docs/en_us/ingress/load-balance.md:
--------------------------------------------------------------------------------
1 | # Load balancing between Services
2 | ## Introduction
3 |
4 | For `Service`s that providing the same service (called Sub-Services), BFE Ingress Controller supports load balancing between them, based on weight configured for each `Service`.
5 |
6 | ## Configuration
7 |
8 | BFE Ingress Controller use `Annotation` to support load-balancing between multiple Sub-Services:
9 |
10 | - in `annotations`
11 |
12 | - configure weight for each Sub-Service.
13 |
14 | - define a `Service` name for the service they provided together:
15 |
16 | ``` yaml
17 | bfe.ingress.kubernetes.io/balance.weight: '{"service": {"sub-service1":80, "sub-service2":20}}'
18 | ```
19 |
20 | - in `rules`
21 |
22 | - set the `serviceName` of `backend` as the `Service` name in `Annotation`, and set the `servicePort`.
23 |
24 | ## Example
25 |
26 | ```yaml
27 | apiVersion: networking.k8s.io/v1beta1
28 | kind: Ingress
29 | metadata:
30 | name: tls-example-ingress
31 | annotations:
32 | kubernetes.io/ingress.class: bfe
33 | bfe.ingress.kubernetes.io/balance.weight: '{"service": {"service1":80, "service2":20}}'
34 | spec:
35 | tls:
36 | - hosts:
37 | - https-example.foo.com
38 | secretName: testsecret-tls
39 | rules:
40 | - host: https-example.foo.com
41 | http:
42 | paths:
43 | - path: /
44 | pathType: Prefix
45 | backend:
46 | serviceName: service
47 | servicePort: 80
48 | ```
49 |
--------------------------------------------------------------------------------
/docs/en_us/ingress/redirect.md:
--------------------------------------------------------------------------------
1 | # Redirect
2 |
3 | The BFE Ingress Controller supports redirecting traffic matched by the Ingress by using `metadata.annotations` of the Ingress object.
4 |
5 | ## How to Config
6 |
7 | In the Ingress object,
8 |
9 | - `spec.rules` defines the route rules;
10 | - `metadata.annotations` defines the behavior of redirecting traffic matched by the Ingress.
11 |
12 | Reference format:
13 |
14 | ```yaml
15 | metadata:
16 | annotations:
17 | bfe.ingress.kubernetes.io/redirect.url-set: "https://www.baidu.com"
18 | spec:
19 | rules:
20 | - ...
21 | ```
22 |
23 | ```yaml
24 | metadata:
25 | annotations:
26 | bfe.ingress.kubernetes.io/redirect.scheme-set: https
27 | bfe.ingress.kubernetes.io/redirect.status: 301
28 | spec:
29 | rules:
30 | - ...
31 | ```
32 |
33 | ## Redirect Location
34 |
35 | The BFE Ingress Controller supports 4 ways to configure the redirect location, and only one of them can be set in an Ingress object.
36 |
37 | ### Static URL
38 |
39 | Use `bfe.ingress.kubernetes.io/redirect.url-set` to config the static redirect location。
40 |
41 | For example:
42 |
43 | ```yaml
44 | bfe.ingress.kubernetes.io/redirect.target: "https://www.baidu.com"
45 | ```
46 |
47 | Corresponding scenario:
48 |
49 | - Request: http://host/path?query-key=value
50 | - Response: https://www.baidu.com
51 |
52 | ### Fetch URL from Query
53 |
54 | Redirect location is fetched from specific Query of request URL, query key is specified by `bfe.ingress.kubernetes.io/redirect.url-from-query`.
55 |
56 | For example:
57 |
58 | ```yaml
59 | bfe.ingress.kubernetes.io/redirect.url-from-query: url
60 | ```
61 |
62 | Corresponding scenario:
63 |
64 | - Request: https://host/path?url=https%3A%2F%2Fwww.baidu.com
65 | - Response: https://www.baidu.com
66 |
67 | ### Add Prefix
68 |
69 | Redirect location is a combination of given prefix and the `Path` of request URL, the prefix is set by `bfe.ingress.kubernetes.io/redirect.url-prefix-add`.
70 |
71 | For example:
72 |
73 | ```yaml
74 | bfe.ingress.kubernetes.io/redirect.url-prefix-add: "http://www.baidu.com/redirect"
75 | ```
76 |
77 | Corresponding scenario:
78 |
79 | - Request: https://host/path?query-key=value
80 | - Response: http://www.baidu.com/redirect/path?query-key=value
81 |
82 | ### Set Scheme
83 |
84 | Change the scheme of the request。Only HTTP and HTTPS are supported.
85 |
86 | For example:
87 |
88 | ```yaml
89 | bfe.ingress.kubernetes.io/redirect.scheme-set: http
90 | ```
91 |
92 | Corresponding scenario:
93 |
94 | - Request: https://host/path?query-key=value
95 | - Response: http://host/path?query-key=value
96 |
97 | ## Response Status Code
98 |
99 | By default, the status code of the redirect response is `302`. Users can manually specify the redirect status code by setting `bfe.ingress.kubernetes.io/redirect.response-status`.
100 |
101 | For example:
102 |
103 | ```yaml
104 | bfe.ingress.kubernetes.io/redirect.response-status: 301
105 | ```
106 |
107 | The supported redirection status codes are: 301, 302, 303, 307, 308.
--------------------------------------------------------------------------------
/docs/en_us/ingress/tls.md:
--------------------------------------------------------------------------------
1 | # TLS Configuration
2 | BFE Ingress Controller manages TLS certificates and secretes in the way defined by Kubernetes.
3 |
4 | TLS certificates and secretes are stored in `Secret`. See examples below:
5 |
6 | **Configure Secret**
7 |
8 | ```yaml
9 | apiVersion: v1
10 | kind: Secret
11 | metadata:
12 | name: testsecret-tls
13 | namespace: default
14 | data:
15 | tls.crt: base64 encoded cert
16 | tls.key: base64 encoded key
17 | type: kubernetes.io/tls
18 | ```
19 | **Configure Ingress**
20 |
21 | ```yaml
22 | apiVersion: networking.k8s.io/v1beta1
23 | kind: Ingress
24 | metadata:
25 | name: tls-example-ingress
26 | spec:
27 | tls:
28 | - hosts:
29 | - https-example.foo.com
30 | secretName: testsecret-tls
31 | rules:
32 | - host: https-example.foo.com
33 | http:
34 | paths:
35 | - path: /
36 | pathType: Prefix
37 | backend:
38 | serviceName: service1
39 | servicePort: 80
40 | ```
41 |
--------------------------------------------------------------------------------
/docs/en_us/ingress/validate-state.md:
--------------------------------------------------------------------------------
1 | # Ingress status
2 |
3 | ## Feedback for ingress status
4 | The validation of the Ingress configuration is an asynchronous process. The status can only be returned after the configuration has taken effect.
5 |
6 | In order to provide feedback for ingress status, BFE Ingress Controller will write status back to its annotations.
7 |
8 | **BFE Ingress Controller defines the annotation for status as follows:**
9 |
10 | ```yaml
11 | #bfe.ingress.kubernetes.io/bfe-ingress-status is the reserved Annotation key of BFE Ingress Controller
12 | #used for status feedback.
13 | # status: success -> ingress is valid, error -> ingress is invalid.
14 | # message: if ingress is invalid, error messages will be recorded
15 | bfe.ingress.kubernetes.io/bfe-ingress-status: {"status": "", "message": ""}
16 | ```
17 | ## Example
18 |
19 | The following example shows the status of two ingresses with route rules conflict.
20 | `Ingress1` and `Ingress2` have one identical route rule (`Host:example.net, Path:/bar`)
21 |
22 | ```yaml
23 | kind: Ingress
24 | apiVersion: networking.k8s.io/v1beta1
25 | metadata:
26 | name: "ingress1"
27 | namespace: production
28 | annotations:
29 | kubernetes.io/ingress.class: bfe
30 | spec:
31 | rules:
32 | - host: example.net
33 | http:
34 | paths:
35 | - path: /bar
36 | backend:
37 | serviceName: service1
38 | servicePort: 80
39 | ---
40 | kind: Ingress
41 | apiVersion: networking.k8s.io/v1beta1
42 | metadata:
43 | name: "ingress2"
44 | namespace: production
45 | annotations:
46 | kubernetes.io/ingress.class: bfe
47 | spec:
48 | rules:
49 | - host: example.net
50 | http:
51 | paths:
52 | - path: /bar
53 | backend:
54 | serviceName: service2
55 | servicePort: 80
56 | ```
57 | According to [principles of handling route rule conflict](conflict.md), `Ingress1` will take effect and `Ingress2` will be ignored. After the status is returned, `status` of `Ingress1` will be "success" and status of `Ingress2` it will be "fail".
58 | ```yaml
59 | kind: Ingress
60 | apiVersion: networking.k8s.io/v1beta1
61 | metadata:
62 | name: "ingress1"
63 | namespace: production
64 | annotations:
65 | kubernetes.io/ingress.class: bfe
66 | bfe.ingress.kubernetes.io/bfe-ingress-status: {"status": "success"}
67 | spec:
68 | rules:
69 | - host: example.net
70 | http:
71 | paths:
72 | - path: /bar
73 | backend:
74 | serviceName: service1
75 | servicePort: 80
76 | ---
77 | kind: Ingress
78 | apiVersion: networking.k8s.io/v1beta1
79 | metadata:
80 | name: "ingress2"
81 | namespace: production
82 | annotations:
83 | kubernetes.io/ingress.class: bfe
84 | bfe.ingress.kubernetes.io/bfe-ingress-status: |
85 | {"status": "fail", "message": "conflict with production/ingress1"}
86 | spec:
87 | rules:
88 | - host: example.net
89 | http:
90 | paths:
91 | - path: /bar
92 | backend:
93 | serviceName: service2
94 | servicePort: 80
95 | ```
96 |
--------------------------------------------------------------------------------
/docs/en_us/rbac.md:
--------------------------------------------------------------------------------
1 | # Role-Based Access Control (RBAC)
2 |
3 | ## Introduction
4 |
5 | This document describes how to deploy BFE Ingress Controller in an environment with RBAC enabled.
6 |
7 | Kubernetes use [Role-based access control](https://kubernetes.io/docs/reference/access-authn-authz/rbac/), and define below objects:
8 |
9 | - Define 'role', to set permissions for the role:
10 | - `ClusterRole` - to define permissions of a role which is cluster-wide
11 | - `Role` - to define permissions of a role which belongs to specific namespace
12 |
13 | - Define 'role binding', to grant permissions defined in a role to a user or set of users:
14 | - `ClusterRoleBinding` , to grant permissions defined in `ClusterRole` to user
15 | - `RoleBinding` , to grant permissions defined in `Role` to user
16 |
17 | To deploy a BFE Ingress Controller instance in an environment with RBAC enabled, use the `ServiceAccount` that bound to a `ClusterRole`, which has been granted with all permissions BFE Ingress Controller required.
18 |
19 | ## Minimum permission set
20 |
21 | BFE Ingress Controller required at least below permissions:
22 |
23 | - permissions defined for a ClusterRole:
24 |
25 | ```yaml
26 | services, endpoints, secrets, namespaces: get, list, watch
27 | ingresses, ingressclasses: get, list, watch, update
28 | ```
29 |
30 | ## Example
31 |
32 | ### Example config files
33 |
34 | [controller.yaml](../../examples/controller.yaml)
35 |
36 | [rbac.yaml](../../examples/rbac.yaml)
37 |
38 | ### Define and refer ServiceAccount
39 |
40 | In [controller.yaml](../../examples/controller.yaml) :
41 |
42 | - define a `ServiceAccount` ,
43 | - name it as `bfe-ingress-controller`
44 | - define a BFE Ingress Controller instance deployment
45 | - Instance deployed should be linked to ServiceAccount `bfe-ingress-controller`
46 |
47 | ### Define ClusterRole
48 |
49 | In [rbac.yaml](../../examples/rbac.yaml) :
50 | - define a `ClusterRole`,
51 | - name it as `bfe-ingress-controller`
52 | - grant cluster-wide permissions below to it:
53 |
54 | ```yaml
55 | services, endpoints, secrets, namespaces: get, list, watch
56 | ingresses, ingressclasses: get, list, watch, update
57 | ```
58 |
59 | ### Bind ClusterRole
60 |
61 | In [rbac.yaml](../../examples/rbac.yaml) :
62 |
63 | - define a `ClusterRoleBinding`,
64 | - bind ServiceAccount `bfe-ingress-controller` to ClusterRole `bfe-ingress-controller`
65 |
66 |
--------------------------------------------------------------------------------
/docs/images/arch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bfenetworks/ingress-bfe/593a473ce6016f41d99de24722008423e5085322/docs/images/arch.jpg
--------------------------------------------------------------------------------
/docs/images/qrcode_for_gh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bfenetworks/ingress-bfe/593a473ce6016f41d99de24722008423e5085322/docs/images/qrcode_for_gh.jpg
--------------------------------------------------------------------------------
/docs/zh_cn/FAQ/FAQ.md:
--------------------------------------------------------------------------------
1 | # 常见问题
2 | 1. 问题:BFE Ingress Controller支持哪些启动参数,如何设置
3 |
4 | 支持的启动参数:
5 |
6 | 选项 | 默认值 | 用途|
7 | | --- | --- | --- |
8 | | --namespace
-n | 空字符串 | 设置需监听的ingress所在的namespace,多个namespace 之间用`,`分割。
默认值为空字符串,表示监听所有的 namespace。 |
9 | | --ingress-class| bfe | 指定需监听的Ingress的`kubernetes.io/ingress.class`值。
如不指定,BFE Ingress Controller将监听class设置为bfe的Ingress。 通常无需设置。 |
10 | | --default-backend| 空字符串 | 指定default-backend服务的名字,格式为`namespace/name`。
如指定default-backend,没有命中任何Ingress规则的请求,将被转发到default-backend。 |
11 |
12 | 设置方式:
13 | 在BFE Ingress Controller的部署文件[controller.yaml](../../../examples/controller.yaml)中指定。例如:
14 | ```yaml
15 | ...
16 | containers:
17 | - name: bfe-ingress-controller
18 | image: bfenetworks/bfe-ingress-controller:latest
19 | args: ["-n", "ns1,ns2", "--default-backend", "test/whoami"]
20 | ...
21 | ```
22 |
--------------------------------------------------------------------------------
/docs/zh_cn/README.md:
--------------------------------------------------------------------------------
1 | # BFE Ingress Controller
2 |
3 | BFE Ingress Controller 是基于 [BFE][] 实现的 Kubernetes [Ingress Controller][],
4 | 用于支持在 Kubernetes 中使用 [Ingress][]。
5 |
6 | [文档列表](SUMMARY.md)
7 |
8 | [Ingress Controller]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/ "Kubernetes"
9 | [Ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/ "Kubernetes"
10 | [BFE]: https://github.com/bfenetworks/bfe "Github"
11 |
--------------------------------------------------------------------------------
/docs/zh_cn/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | [comment]: <> "For user"
4 | * 部署
5 | * [部署指南](deployment.md)
6 | * [基于角色的访问控制(RBAC)](rbac.md)
7 | * 配置
8 | * [配置指南](ingress/basic.md)
9 | * [生效状态](ingress/validate-state.md)
10 | * [路由优先级](ingress/priority.md)
11 | * [路由冲突处理](ingress/conflict.md)
12 | * [TLS 配置](ingress/tls.md)
13 | * [负载均衡](ingress/load-balance.md)
14 | * [重定向](ingress/redirect.md)
15 | * [URL重写](ingress/rewrite.md)
16 | * 配置示例
17 | * [配置文件示例](example/example.md)
18 | * [灰度发布示例](example/canary-release.md)
19 | * [常见问题](FAQ/FAQ.md)
20 | * 附录
21 | * [Annotations](appendix/annotations.md)
22 | ---
23 |
24 | [comment]: <> "For developer"
25 | * [参与贡献](contribute/how-to-contribute.md)
26 | * [如何贡献代码](contribute/contribute-codes.md)
27 | * [代码结构说明](development/source-code-layout.md)
28 | * [核心工作原理](development/core-logic.md)
29 | * [Annotation 开发指南](development/annotation-implement-guide.md)
30 | * [如何贡献文档](contribute/contribute-documents.md)
31 | * [版本发布说明](https://www.bfe-networks.net/zh_cn/development/release_regulation/)
32 |
33 |
--------------------------------------------------------------------------------
/docs/zh_cn/contribute/contribute-documents.md:
--------------------------------------------------------------------------------
1 | # 如何贡献文档
2 | ## 文档要求
3 | - 所有内容都应该以 [Markdown][markdown] (GitHub风格)的形式编写,文件以`.md`为后缀
4 | - 如果是新增文档,需将新增的文档名,添加到对应的index文件中([SUMMARY.md](../SUMMARY.md))
5 | ## 文档开发流程
6 |
7 | 1. 编写文档
8 | 1. 运行预览工具,并预览修改
9 | - [如何使用预览工具](https://www.bfe-networks.net/zh_cn/development/write_doc_guide/#_2)
10 | 1. 提交修改
11 | - 修改文档, 提交修改与PR的步骤可以参考[代码开发流程](contribute-codes.md#代码开发流程)
12 |
13 | > 可参考 BFE [如何贡献文档](https://www.bfe-networks.net/zh_cn/development/write_doc_guide/)
14 |
15 | [markdown]: https://guides.github.com/features/mastering-markdown/
--------------------------------------------------------------------------------
/docs/zh_cn/contribute/how-to-contribute.md:
--------------------------------------------------------------------------------
1 | # 参与贡献
2 | - [如何贡献代码](contribute-codes.md)
3 | - [如何贡献文档](contribute-documents.md)
4 | - [版本发布说明](https://www.bfe-networks.net/zh_cn/development/release_regulation/)
5 |
--------------------------------------------------------------------------------
/docs/zh_cn/deployment.md:
--------------------------------------------------------------------------------
1 | # 部署指南
2 |
3 | ## 安装
4 | 可通过下述两种方式中任意一种进行安装:
5 |
6 | * 通过配置文件安装
7 | * 通过helm安装
8 |
9 | ### 配置文件安装
10 |
11 | ``` shell script
12 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/controller-all.yaml
13 | ```
14 |
15 | - 配置文件中使用了Docker Hub 上的[BFE Ingress Controller镜像](https://hub.docker.com/r/bfenetworks/bfe-ingress-controller)的最新版本。如需使用指定版本的镜像,修改配置文件,指定镜像版本。
16 | - 权限配置具体说明可参见[RBAC 文件编写指南](rbac.md)。
17 |
18 | ### Helm安装
19 |
20 | ```
21 | helm upgrade --install bfe-ingress-controller bfe-ingress-controller --repo https://bfenetworks.github.io/ingress-bfe --namespace ingress-bfe --create-namespace
22 | ```
23 | - 要求helm3
24 |
25 | ## 测试
26 | * 创建测试服务whoami
27 | ``` shell script
28 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/whoami.yaml
29 | ```
30 |
31 | * 创建k8s Ingress资源,验证消息路由
32 | ``` shell script
33 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/ingress.yaml
34 | ```
35 |
36 | * 创建k8s Ingress资源,验证消息路由 (kubernetes version >=1.19)
37 | ``` shell script
38 | kubectl apply -f https://raw.githubusercontent.com/bfenetworks/ingress-bfe/develop/examples/ingress-v1.19.yaml
39 |
40 | ```
41 |
42 |
--------------------------------------------------------------------------------
/docs/zh_cn/development/core-logic.md:
--------------------------------------------------------------------------------
1 | # BFE Ingress Controller 工作原理
2 |
3 | ## 核心处理逻辑
4 |
5 | > 前置知识
6 | > - 什么是 [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
7 | > - 什么是 [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)
8 |
9 | 
10 |
11 | BFE Ingress Controller 的核心处理逻辑是:
12 | 1. 监听获取 k8s 集群中的 Ingress 资源
13 | 2. 解析 Ingress 资源中定义的配置逻辑,生成对应的 BFE 配置
14 | 3. 使新生成的 BFE 配置在 BFE进程中生效
15 |
16 | ## 如何实现 Ingress 资源的监听
17 |
18 | 通过 [Kubernetes controller-runtime][] 框架实现:
19 | 1. 创建 Manager,Manager 内部维护了 Client、Cache 和 Schema 等
20 | 2. 创建 Reconciler,并实现回调逻辑
21 | 3. 使用 Builder 模式创建 Controller,并指定监听 Ingress 资源和对应的 Reconcile
22 | 4. 启动 Manager
23 |
24 | ## BFE配置如何定义
25 |
26 | BFE 的配置定义可以通过以下方式获得:
27 | 1. 官网文档:[配置概述][](主要关注动态配置)
28 | 2. BFE 源码: bfe/[bfe_modules][]/mod_\*/\*_load.go
29 |
30 | 官网更新可能存在延迟,以源代码为准。
31 |
32 | > 常见动态配置:
33 | > - 流量路由配置
34 | > - [域名规则配置](https://www.bfe-networks.net/zh_cn/configuration/server_data_conf/host_rule.data/)
35 | > - [分流规则配置](https://www.bfe-networks.net/zh_cn/configuration/server_data_conf/route_rule.data/)
36 | > - 负载均衡配置
37 | > - [子集群负载均衡配置](https://www.bfe-networks.net/zh_cn/configuration/cluster_conf/gslb.data/)
38 | > - 接入协议配置
39 | > - [TLS协议配置](https://www.bfe-networks.net/zh_cn/configuration/tls_conf/tls_rule_conf.data/)
40 | > - 扩展模块配置
41 | > - [mod_header 配置](https://www.bfe-networks.net/zh_cn/modules/mod_header/mod_header/)
42 | > - [mod_redirect 配置](https://www.bfe-networks.net/zh_cn/modules/mod_redirect/mod_redirect/)
43 | > - [mod_rewrite 配置](https://www.bfe-networks.net/zh_cn/modules/mod_rewrite/mod_rewrite/)
44 |
45 | ## BFE配置如何生效
46 |
47 | 通过 BFE [配置热加载][],完成在 BFE 不停机的情况下更新动态配置。
48 |
49 | [Kubernetes controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime
50 | [配置概述]: https://www.bfe-networks.net/zh_cn/configuration/config/
51 | [bfe_modules]: https://github.com/bfenetworks/bfe/tree/develop/bfe_modules
52 | [配置热加载]: https://www.bfe-networks.net/zh_cn/operation/reload/
--------------------------------------------------------------------------------
/docs/zh_cn/development/source-code-layout.md:
--------------------------------------------------------------------------------
1 | # BFE Ingress 源代码框架
2 |
3 | ```shell
4 | .
5 | ├── .github : Github 工作流目录
6 | ├── build : 编译脚本目录
7 | ├── charts : BFE Ingress Controller 的 Helm Charts目录
8 | ├── cmd
9 | │ └── ingress-controller : 主程序目录
10 | ├── docs : 中英文用户文档及其素材目录
11 | ├── examples : k8s 资源描述文件示例目录
12 | ├── internal : 核心源码目录
13 | │ ├── bfeConfig : BFE Ingress Controller 配置选项定义代码
14 | │ ├── controllers : k8s 集群交互相关代码,主要包含各资源的controller的实现以及reconcile逻辑
15 | │ └── option : BFE 配置相关代码,主要包含各 BFE 配置的生成和热加载逻辑
16 | ├── scripts : 镜像依赖的脚本目录
17 | ├── CHANGELOG.md : 版本修改日志
18 | ├── Dockerfile : 构建镜像的指令文件
19 | ├── LICENSE : License 协议
20 | ├── Makefile : 程序编译与镜像制作的指令文件
21 | ├── SECURITY.md : 安全策略
22 | ├── VERSION : 程序版本
23 | ├── go.mod : Go 语言依赖管理文件
24 | └── go.sum : Go 语言依赖管理文件
25 | ```
26 |
27 | ## 核心代码
28 | - /[internal][]: 核心源码目录
29 | - /[option][]: BFE Ingress Controller 配置选项定义代码
30 | - /[controllers][]: k8s 集群交互相关代码,主要包含各资源的controller的实现以及reconcile逻辑
31 | - /[bfeConfig][]: BFE 配置相关代码,主要包含各 BFE 配置的生成和热加载逻辑
32 |
33 | ## 持续集成
34 |
35 | ### 工作流
36 | - /[.github][]: Github 工作流目录
37 | - /[Makefile][]: 程序编译与镜像制作的指令文件
38 |
39 | ### 程序编译
40 | - /cmd/[ingress-controller][]: 主程序目录
41 | - /[VERSION][]: 程序版本
42 | - /[build][]: 编译脚本目录
43 | - /[go.mod][]: Go 语言依赖管理文件
44 | - /[go.sum][]: Go 语言依赖管理文件
45 |
46 | ### 镜像制作
47 | - /[Dockerfile][]: 构建镜像的指令文件
48 | - /[scripts][]: 镜像依赖的脚本目录(如镜像启动脚本)
49 |
50 | ## Helm 支持
51 | - /[charts][]: BFE Ingress Controller 的 Helm Charts
52 |
53 | ## 项目文档
54 | - /[docs][]: 中英文用户文档及其素材目录
55 | - /[examples][]: k8s 资源描述文件示例目录
56 | - /[CHANGELOG.md][]: 版本修改日志
57 | - /[LICENSE][]: License 协议
58 | - /[SECURITY.md][]: 安全策略
59 |
60 | [.github]: ../../../.github
61 | [build]: ../../../build
62 | [charts]: ../../../charts
63 | [ingress-controller]: ../../../cmd/ingress-controller
64 | [docs]: ../../../docs
65 | [examples]: ../../../examples
66 | [internal]: ../../../internal
67 | [bfeConfig]: ../../../internal/bfeConfig
68 | [controllers]: ../../../internal/controllers
69 | [go.mod]: ../../../go.mod
70 | [go.sum]: ../../../go.sum
71 | [option]: ../../../internal/option
72 | [scripts]: ../../../scripts
73 | [CHANGELOG.md]: ../../../CHANGELOG.md
74 | [Dockerfile]: ../../../Dockerfile
75 | [LICENSE]: ../../../LICENSE
76 | [Makefile]: ../../../Makefile
77 | [SECURITY.md]: ../../../SECURITY.md
78 | [VERSION]: ../../../VERSION
--------------------------------------------------------------------------------
/docs/zh_cn/example/canary-release.md:
--------------------------------------------------------------------------------
1 | # 支持灰度发布
2 |
3 | ## 说明
4 | BFE-Ingress-controller支持通过配置`Annotation`,实现基于`Header/Cookie`的灰度发布功能。
5 |
6 | ## 配置示例
7 | * 初始的ingress配置如下,请求转发到服务`service`:
8 | ```yaml
9 | kind: Ingress
10 | apiVersion: networking.k8s.io/v1beta1
11 | metadata:
12 | name: "original"
13 | namespace: production
14 |
15 | spec:
16 | rules:
17 | - host: example.net
18 | http:
19 | paths:
20 | - path: /bar
21 | pathType: Exact
22 | backend:
23 | serviceName: service
24 | servicePort: 80
25 | ```
26 |
27 | * 做灰度发布,对特定请求,转发到新的服务`service2`。
28 | * 为实现上述目的,创建一个新的ingress,在annotations中包含特定请求的header或cookie的信息。
29 | ```yaml
30 | kind: Ingress
31 | apiVersion: networking.k8s.io/v1beta1
32 | metadata:
33 | name: "greyscale"
34 | namespace: production
35 | annotations:
36 | bfe.ingress.kubernetes.io/router.cookie: "key: value"
37 | bfe.ingress.kubernetes.io/router.header: "Key: Value"
38 |
39 | spec:
40 | rules:
41 | - host: example.net
42 | http:
43 | paths:
44 | - path: /bar
45 | pathType: Exact
46 | backend:
47 | serviceName: service2
48 | servicePort: 80
49 |
50 | ```
51 | * 基于上面的配置,BFE对
52 | 1. 满足 `host == example.net && path == /bar && cookie[key] == value && Header[Key] == Value`,
53 | 则转发到`service-new`集群
54 | 1. 仅满足 `host == example.net && path == /bar`,
55 | 仍转发到`service`集群
56 |
--------------------------------------------------------------------------------
/docs/zh_cn/example/example.md:
--------------------------------------------------------------------------------
1 | # 配置文件示例
2 |
3 | ## deployment
4 | | 程序 | 文件 | 说明 |
5 | | ---- | ---- | ---- |
6 | | bfe-ingress-controller | [controller.yaml](../../../examples/controller.yaml)| 用于 bfe ingress controller 的部署|
7 | | 示例后端服务 whoami | [whoami.yaml](../../../examples/whoami.yaml) | 用于示例服务(whoami)的部署 |
8 |
9 | ## ingress
10 | | 文件 | 说明 |
11 | | ---- | ---- |
12 | | [ingress.yaml](../../../examples/ingress.yaml) | 用于配置示例服务(whoami)流量的路由 |
13 |
14 | ## rbac
15 | | 文件 | 说明 |
16 | | ---- | ---- |
17 | | [rbac.yaml](../../../examples/rbac.yaml) | 用于授予 bfe ingress controller 的权限 |
18 |
19 |
--------------------------------------------------------------------------------
/docs/zh_cn/example/example.md.orig:
--------------------------------------------------------------------------------
1 | # 部署配置示例
2 |
3 | ## deployment
4 | | 程序 | 文件 | 说明 |
5 | | ---- | ---- | ---- |
6 | | bfe ingress controller | [controller.yaml](../../../examples/controller.yaml)| 用于 bfe ingress controller 的部署|
7 | | 示例后端服务 whoami | [whoami.yaml](../../../examples/whoami.yaml) | 用于示例服务(whoami)的部署 |
8 |
9 | ## ingress
10 | | 文件 | 说明 |
11 | | ---- | ---- |
12 | | [ingress.yaml](../../../examples/ingress.yaml) | 用于配置示例服务(whoami)的流量调度 |
13 |
14 | ## rbac
15 | | 文件 | 说明 |
16 | | ---- | ---- |
17 | | [rbac.yaml](../../../examples/rbac.yaml) | 用于授予 bfe ingress controller 的权限 |
18 |
19 |
--------------------------------------------------------------------------------
/docs/zh_cn/ingress/conflict.md:
--------------------------------------------------------------------------------
1 | # 路由冲突处理
2 |
3 | ## 路由冲突的定义
4 |
5 | 当Ingress配置最终生成包含相同的Ingress规则(Host、Path、高级匹配条件均完全相同)的Ingress资源的情况下,会产生路由冲突。
6 |
7 | ## 处理原则:最先创建的生效
8 |
9 | 对存在路由冲突的多个Ingress资源,BFE Ingress Controller将按照"最先创建的生效"的原则,仅使最早被创建的Ingress资源生效。
10 |
11 | 在同一个namespace之间,或在多个namespace之间的路由冲突,均按照此原则处理。
12 |
13 | 对于因路由冲突导致的没有在BFE Ingress Controller中生效的Ingress资源,可在[生效状态](validate-state.md)反馈的Annotation中查找相应的错误消息。
14 |
15 | ## 示例
16 |
17 | ```yaml
18 | apiVersion: networking.k8s.io/v1beta1
19 | kind: Ingress
20 | metadata:
21 | name: ingress-A
22 | namespace: production
23 | annotations:
24 | kubernetes.io/ingress.class: bfe
25 | spec:
26 | rules:
27 | - host: example.foo.com
28 | http:
29 | paths:
30 | - path: /foo
31 | pathType: Prefix
32 | backend:
33 | serviceName: service1
34 | servicePort: 80
35 | ---
36 | apiVersion: networking.k8s.io/v1beta1
37 | kind: Ingress
38 | metadata:
39 | name: ingress-B
40 | namespace: production
41 | annotations:
42 | kubernetes.io/ingress.class: bfe
43 | spec:
44 | rules:
45 | - host: example.foo.com
46 | http:
47 | paths:
48 | - path: /foo
49 | pathType: Prefix
50 | backend:
51 | serviceName: service2
52 | servicePort: 80
53 |
54 | ```
55 | 在以上配置中,ingress-A和ingress-B冲突,ingress-A先于ingress-B创建,所以最终仅ingress-A生效。
56 |
57 | ## 生效状态反馈
58 | 若一个Ingress资源因路由冲突而被忽略(未生效),生效状态反馈回写后,对于生效状态的注解的status会被设为“fail”,message中会包含和哪个Ingress资源发生了冲突。
59 |
60 | 在前面的示例中,ingress-B的生效状态的注解将会如下面所示:
61 |
62 |
63 | ```yaml
64 | metadata:
65 | annotations:
66 | bfe.ingress.kubernetes.io/bfe-ingress-status: |
67 | {"status": "fail", "message": "conflict with production/ingress-A"}
68 | ```
69 |
70 | 更多生效状态的说明见[生效状态](validate-state.md)。
71 |
72 |
--------------------------------------------------------------------------------
/docs/zh_cn/ingress/load-balance.md:
--------------------------------------------------------------------------------
1 | # 多Service之间的负载均衡
2 | ## 说明
3 |
4 | BFE Ingress Controller支持在提供相同服务的多个Service(为便于理解,在BFE Ingress文档中称其为子服务,Sub-Service)之间按权重进行负载均衡。
5 |
6 | 配置方式
7 |
8 | BFE Ingress Controller通过`注解`(`Annotation`)的方式支持多个Sub-Service之间的负载均衡。配置方式为:
9 |
10 | - 在`annotations`中
11 |
12 | - 为多个Sub-Service分别指定流量分配权重
13 |
14 | - 为它们提供的服务设置一个Service名称
15 |
16 | - 格式如下:
17 |
18 | ``` yaml
19 | bfe.ingress.kubernetes.io/balance.weight: '{"service": {"sub-service1":80, "sub-service2":20}}'
20 | ```
21 |
22 | - 在`rules`中
23 |
24 | - 将backend的serviceName设置为注解中设置的Service名称,并指定servicePort
25 |
26 | ## 示例
27 |
28 | ```yaml
29 | apiVersion: networking.k8s.io/v1beta1
30 | kind: Ingress
31 | metadata:
32 | name: tls-example-ingress
33 | annotations:
34 | kubernetes.io/ingress.class: bfe
35 | bfe.ingress.kubernetes.io/balance.weight: '{"service": {"service1":80, "service2":20}}'
36 | spec:
37 | tls:
38 | - hosts:
39 | - https-example.foo.com
40 | secretName: testsecret-tls
41 | rules:
42 | - host: https-example.foo.com
43 | http:
44 | paths:
45 | - path: /
46 | pathType: Prefix
47 | backend:
48 | serviceName: service
49 | servicePort: 80
50 | ```
--------------------------------------------------------------------------------
/docs/zh_cn/ingress/redirect.md:
--------------------------------------------------------------------------------
1 | # 重定向配置
2 |
3 | BFE Ingress Controller支持通过在声明在Ingress中使用注解(Annotations)的方式,对当前Ingress匹配的流量进行重定向。
4 |
5 | ## 配置方式
6 |
7 | Ingress 资源内
8 |
9 | - `spec.rules`定义路由规则
10 | - `metadata.annotations`定义对符合路由规则的流量,重定向响应的行为
11 |
12 | 参考格式:
13 |
14 | ```yaml
15 | metadata:
16 | annotations:
17 | bfe.ingress.kubernetes.io/redirect.url-set: "https://www.baidu.com"
18 | spec:
19 | rules:
20 | - ...
21 | ```
22 |
23 | ```yaml
24 | metadata:
25 | annotations:
26 | bfe.ingress.kubernetes.io/redirect.scheme-set: https
27 | bfe.ingress.kubernetes.io/redirect.status: 301
28 | spec:
29 | rules:
30 | - ...
31 | ```
32 |
33 | ## 重定向Location
34 |
35 | BFE Ingress Controller支持使用4种方式配置重定向目标URL,并且每个Ingress对象仅允许使用一种配置方式。
36 |
37 | ### 静态URL
38 |
39 | 通过设置 `bfe.ingress.kubernetes.io/redirect.url-set`,配置静态重定向目标URL。
40 |
41 | 例如:
42 |
43 | ```yaml
44 | bfe.ingress.kubernetes.io/redirect.target: "https://www.baidu.com"
45 | ```
46 |
47 | 对应示例
48 |
49 | - Request: http://host/path?query-key=value
50 | - Response: https://www.baidu.com
51 |
52 | ### 从Query中获得URL
53 |
54 | 从请求URL的指定`Query`值中获取重定向目标URL。通过设置`bfe.ingress.kubernetes.io/redirect.url-from-query`指定Query名。
55 |
56 | 例如:
57 |
58 | ```yaml
59 | bfe.ingress.kubernetes.io/redirect.url-from-query: url
60 | ```
61 |
62 | 对应示例
63 |
64 | - Request: https://host/path?url=https%3A%2F%2Fwww.baidu.com
65 | - Response: https://www.baidu.com
66 |
67 | ### 添加前缀
68 |
69 | 重定向目标URL由指定前缀和请求URL的`Path`拼接而成。通过`bfe.ingress.kubernetes.io/redirect.url-prefix-add`设置拼接的前缀字符串。
70 |
71 | 例如:
72 |
73 | ```yaml
74 | bfe.ingress.kubernetes.io/redirect.url-prefix-add: "http://www.baidu.com/redirect"
75 | ```
76 |
77 | 对应示例
78 |
79 | - Request: https://host/path?query-key=value
80 | - Response: http://www.baidu.com/redirect/path?query-key=value
81 |
82 | ### 设置Scheme
83 |
84 | 修改请求的协议。目前仅支持HTTP和HTTPS。
85 |
86 | 例如:
87 |
88 | ```yaml
89 | bfe.ingress.kubernetes.io/redirect.scheme-set: http
90 | ```
91 |
92 | 对应示例
93 |
94 | - Request: https://host/path?query-key=value
95 | - Response: http://host/path?query-key=value
96 |
97 | ## 重定向状态码
98 |
99 | 默认情况下,重定向Response的状态码为302。也可以通过设置 `bfe.ingress.kubernetes.io/redirect.response-status`,手动指定重定向的状态码。
100 |
101 | 例如:
102 |
103 | ```yaml
104 | bfe.ingress.kubernetes.io/redirect.response-status: 301
105 | ```
106 |
107 | 目前支持的重定向状态码有:301、302、303、307、308。
--------------------------------------------------------------------------------
/docs/zh_cn/ingress/tls.md:
--------------------------------------------------------------------------------
1 | # TLS 配置
2 | BFE Ingress Controller按照Kubernetes原生定义的方式来管理TLS的证书和密钥。
3 |
4 | TLS的证书和密钥通过Secrets进行保存,示例如下:
5 |
6 | **Secret配置**
7 |
8 | ```yaml
9 | apiVersion: v1
10 | kind: Secret
11 | metadata:
12 | name: testsecret-tls
13 | namespace: default
14 | data:
15 | tls.crt: base64 encoded cert
16 | tls.key: base64 encoded key
17 | type: kubernetes.io/tls
18 | ```
19 | **Ingress配置**
20 | ```yaml
21 | apiVersion: networking.k8s.io/v1beta1
22 | kind: Ingress
23 | metadata:
24 | name: tls-example-ingress
25 | annotations:
26 | kubernetes.io/ingress.class: bfe
27 | spec:
28 | tls:
29 | - hosts:
30 | - https-example.foo.com
31 | secretName: testsecret-tls
32 | rules:
33 | - host: https-example.foo.com
34 | http:
35 | paths:
36 | - path: /
37 | pathType: Prefix
38 | backend:
39 | serviceName: service1
40 | servicePort: 80
41 | ```
42 |
--------------------------------------------------------------------------------
/docs/zh_cn/ingress/validate-state.md:
--------------------------------------------------------------------------------
1 | # 生效状态
2 |
3 | ## 生效状态反馈
4 | Ingress配置的合法性检查是一个异步过程,检查结果在配置生效的过程中才能返回。
5 |
6 | 为了能给用户反馈当前Ingress是否生效,BFE Ingress Controller会将Ingress的实际生效状态回写到Ingress的一个Annotation当中。
7 | **BFE Ingress Controller的状态Annotation定义如下:**
8 |
9 | ```yaml
10 | #bfe.ingress.kubernetes.io/bfe-ingress-status为BFE-Ingress预留的Annotation key,
11 | #用于BFE-Ingress反馈生效状态
12 | # status: 表示当前ingress是否合法, 取值为:success -> ingress合法, error -> ingress不合法
13 | # message: 当ingress不合法的情况下,message记录错误详细原因。
14 | bfe.ingress.kubernetes.io/bfe-ingress-status: {"status": "", "message": ""}
15 | ```
16 | ## 示例
17 |
18 | 下面是BFE-Ingress生效状态反馈的一个示例,展示发生路由冲突的两个Ingress资源的生效状态反馈。
19 | `Ingress1`和`Ingress2`的路由规则完全一样(`Host:example.net, Path:/bar`)。
20 |
21 | ```yaml
22 | kind: Ingress
23 | apiVersion: networking.k8s.io/v1beta1
24 | metadata:
25 | name: "ingress1"
26 | namespace: production
27 | annotations:
28 | kubernetes.io/ingress.class: bfe
29 | spec:
30 | rules:
31 | - host: example.net
32 | http:
33 | paths:
34 | - path: /bar
35 | backend:
36 | serviceName: service1
37 | servicePort: 80
38 | ---
39 | kind: Ingress
40 | apiVersion: networking.k8s.io/v1beta1
41 | metadata:
42 | name: "ingress2"
43 | namespace: production
44 | annotations:
45 | kubernetes.io/ingress.class: bfe
46 | spec:
47 | rules:
48 | - host: example.net
49 | http:
50 | paths:
51 | - path: /bar
52 | backend:
53 | serviceName: service2
54 | servicePort: 80
55 | ```
56 | 根据[路由冲突处理原则](conflict.md),`Ingress1`将生效,而`Ingress2`将被忽略。状态回写反馈后,`Ingress1`的状态为success,而`Ingress2`的状态为fail。
57 | ```yaml
58 | kind: Ingress
59 | apiVersion: networking.k8s.io/v1beta1
60 | metadata:
61 | name: "ingress1"
62 | namespace: production
63 | annotations:
64 | kubernetes.io/ingress.class: bfe
65 | bfe.ingress.kubernetes.io/bfe-ingress-status: {"status": "success"}
66 | spec:
67 | rules:
68 | - host: example.net
69 | http:
70 | paths:
71 | - path: /bar
72 | backend:
73 | serviceName: service1
74 | servicePort: 80
75 | ---
76 | kind: Ingress
77 | apiVersion: networking.k8s.io/v1beta1
78 | metadata:
79 | name: "ingress2"
80 | namespace: production
81 | annotations:
82 | kubernetes.io/ingress.class: bfe
83 | bfe.ingress.kubernetes.io/bfe-ingress-status: |
84 | {"status": "fail", "message": "conflict with production/ingress1"}
85 | spec:
86 | rules:
87 | - host: example.net
88 | http:
89 | paths:
90 | - path: /bar
91 | backend:
92 | serviceName: service2
93 | servicePort: 80
94 | ```
95 |
--------------------------------------------------------------------------------
/docs/zh_cn/rbac.md:
--------------------------------------------------------------------------------
1 | # 基于角色的访问控制(RBAC)
2 |
3 | ## 说明
4 |
5 | 本文档说明如何在启用了RBAC的环境中部署BFE Ingress controller。
6 |
7 | Kubernetes 中,采用[基于角色的访问控制](https://kubernetes.io/docs/reference/access-authn-authz/rbac/),使用了如下对象:
8 |
9 | - 通过定义角色,配置角色相关的权限:
10 | - `ClusterRole` - 定义适用于整个集群的角色及其所具有的权限
11 | - `Role` - 定义适用于特定名称空间的角色及其所具有的权限
12 |
13 | - 通过配置角色绑定,可以将角色中定义的权限赋予一个或者一组用户
14 | - `ClusterRoleBinding` ,赋予用户`ClusterRole`角色中定义的权限
15 | - `RoleBinding` ,赋予用户`ClusterRole`角色中定义的权限
16 |
17 | 在启用了RBAC的环境中部署BFE Ingress Controller,应该将其关联到一个`ServiceAccount`,且该`ServiceAccount`需要绑定到具有BFE Ingress Controller所需权限的`ClusterRole`。
18 |
19 | ## 最小权限集
20 |
21 | BFE Ingress Controller所需要的权限至少应该包括:
22 |
23 | - 具有ClusterRole中定义的如下权限:
24 |
25 | ```yaml
26 | services, endpoints, secrets, namespaces: get, list, watch
27 | ingresses, ingressclasses: get, list, watch, update
28 | ```
29 |
30 | ## 示例
31 |
32 | ### 示例配置文件controller
33 |
34 | [controller.yaml](../../examples/controller.yaml)
35 |
36 | [rbac.yaml](../../examples/rbac.yaml)
37 |
38 | ### 创建并引用ServiceAccount
39 |
40 | 在 [controller.yaml](../../examples/controller.yaml) 中:
41 |
42 | - 定义一个 `ServiceAccount` ,
43 | - 命名为`bfe-ingress-controller`
44 | - 定义了BFE Ingress Controller的部署
45 | - 部署的实例关联 ServiceAccount `bfe-ingress-controller`
46 |
47 | ### 创建ClusterRole
48 |
49 | 在 [rbac.yaml](../../examples/rbac.yaml) 中:
50 | - 定义了一个`ClusterRole`,
51 | - 命名为`bfe-ingress-controller`
52 | - 定义了它具有如下的集群权限(适用于整个集群):
53 |
54 | ```yaml
55 | services, endpoints, secrets, namespaces: get, list, watch
56 | ingresses, ingressclasses: get, list, watch, update
57 | ```
58 |
59 | ### 绑定ClusterRole
60 |
61 | 在 [rbac.yaml](../../examples/rbac.yaml) 中:
62 |
63 | - 定义了一个`ClusterRoleBinding`,
64 | - 将 ServiceAccount `bfe-ingress-controller` 绑定到 ClusterRole `bfe-ingress-controller`
65 |
66 |
--------------------------------------------------------------------------------
/examples/controller.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: ingress-bfe
5 | labels:
6 | app.kubernetes.io/name: bfe-ingress-controller
7 | app.kubernetes.io/instance: bfe-ingress-controller
8 |
9 | ---
10 | apiVersion: v1
11 | kind: ServiceAccount
12 | metadata:
13 | name: bfe-ingress-controller
14 | namespace: ingress-bfe
15 | labels:
16 | app.kubernetes.io/name: bfe-ingress-controller
17 | app.kubernetes.io/instance: bfe-ingress-controller
18 |
19 | ---
20 | kind: Deployment
21 | apiVersion: apps/v1
22 | metadata:
23 | name: bfe-ingress-controller
24 | namespace: ingress-bfe
25 | labels:
26 | app.kubernetes.io/name: bfe-ingress-controller
27 | app.kubernetes.io/instance: bfe-ingress-controller
28 |
29 | spec:
30 | replicas: 1
31 | selector:
32 | matchLabels:
33 | app.kubernetes.io/name: bfe-ingress-controller
34 | app.kubernetes.io/instance: bfe-ingress-controller
35 | template:
36 | metadata:
37 | labels:
38 | app.kubernetes.io/name: bfe-ingress-controller
39 | app.kubernetes.io/instance: bfe-ingress-controller
40 | spec:
41 | serviceAccountName: bfe-ingress-controller
42 | containers:
43 | - name: bfe-ingress-controller
44 | image: bfenetworks/bfe-ingress-controller:latest
45 | ports:
46 | - name: http
47 | containerPort: 8080
48 | - name: https
49 | containerPort: 8443
50 | - name: monitor
51 | containerPort: 8421
52 |
53 | ---
54 | apiVersion: v1
55 | kind: Service
56 | metadata:
57 | name: bfe-controller-service
58 | namespace: ingress-bfe
59 | labels:
60 | app.kubernetes.io/name: bfe-ingress-controller
61 | app.kubernetes.io/instance: bfe-ingress-controller
62 | spec:
63 | type: NodePort
64 | selector:
65 | app.kubernetes.io/name: bfe-ingress-controller
66 | app.kubernetes.io/instance: bfe-ingress-controller
67 | ports:
68 | - name: http
69 | port: 8080
70 | targetPort: 8080
71 | - name: https
72 | port: 8443
73 | targetPort: 8443
74 |
--------------------------------------------------------------------------------
/examples/ingress-v1.19.yaml:
--------------------------------------------------------------------------------
1 | kind: Ingress
2 | apiVersion: networking.k8s.io/v1
3 | metadata:
4 | name: ingress-test
5 | namespace: ingress-bfe
6 | annotations:
7 | kubernetes.io/ingress.class: bfe
8 |
9 | spec:
10 | rules:
11 | - host: "foo.com"
12 | http:
13 | paths:
14 | - path: /whoami
15 | pathType: Prefix
16 | backend:
17 | service:
18 | name: whoami
19 | port:
20 | number: 80
21 |
--------------------------------------------------------------------------------
/examples/ingress.yaml:
--------------------------------------------------------------------------------
1 | kind: Ingress
2 | apiVersion: networking.k8s.io/v1beta1
3 | metadata:
4 | name: ingress-test
5 | namespace: ingress-bfe
6 | annotations:
7 | kubernetes.io/ingress.class: bfe
8 |
9 | spec:
10 | rules:
11 | - host: "foo.com"
12 | http:
13 | paths:
14 | - path: /whoami
15 | backend:
16 | serviceName: whoami
17 | servicePort: 80
18 |
--------------------------------------------------------------------------------
/examples/rbac.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | kind: ClusterRole
3 | apiVersion: rbac.authorization.k8s.io/v1
4 | metadata:
5 | name: bfe-ingress-controller
6 | labels:
7 | app.kubernetes.io/name: bfe-ingress-controller
8 | app.kubernetes.io/instance: bfe-ingress-controller
9 | rules:
10 | - apiGroups:
11 | - ""
12 | resources:
13 | - services
14 | - endpoints
15 | - secrets
16 | - namespaces
17 | verbs:
18 | - get
19 | - list
20 | - watch
21 | - apiGroups:
22 | - ""
23 | resources:
24 | - events
25 | verbs:
26 | - create
27 | - patch
28 | - apiGroups:
29 | - extensions
30 | resources:
31 | - ingresses
32 | - ingressclasses
33 | verbs:
34 | - get
35 | - list
36 | - watch
37 | - update
38 | - patch
39 | - apiGroups:
40 | - networking.k8s.io
41 | resources:
42 | - ingresses
43 | - ingressclasses
44 | verbs:
45 | - get
46 | - list
47 | - watch
48 | - update
49 | - patch
50 |
51 | ---
52 | kind: ClusterRoleBinding
53 | apiVersion: rbac.authorization.k8s.io/v1
54 | metadata:
55 | name: bfe-ingress-controller
56 | labels:
57 | app.kubernetes.io/name: bfe-ingress-controller
58 | app.kubernetes.io/instance: bfe-ingress-controller
59 | roleRef:
60 | apiGroup: rbac.authorization.k8s.io
61 | kind: ClusterRole
62 | name: bfe-ingress-controller
63 | subjects:
64 | - kind: ServiceAccount
65 | name: bfe-ingress-controller
66 | namespace: ingress-bfe
67 |
--------------------------------------------------------------------------------
/examples/whoami.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | name: whoami
5 | namespace: ingress-bfe
6 | labels:
7 | app.kubernetes.io/name: whoami
8 | app.kubernetes.io/instance: whoami
9 | spec:
10 | replicas: 1
11 | selector:
12 | matchLabels:
13 | app.kubernetes.io/name: whoami
14 | app.kubernetes.io/instance: whoami
15 | template:
16 | metadata:
17 | labels:
18 | app.kubernetes.io/name: whoami
19 | app.kubernetes.io/instance: whoami
20 | spec:
21 | containers:
22 | - name: containouswhoami
23 | image: containous/whoami
24 | ports:
25 | - containerPort: 80
26 |
27 | ---
28 | apiVersion: v1
29 | kind: Service
30 | metadata:
31 | name: whoami
32 | namespace: ingress-bfe
33 |
34 | spec:
35 | ports:
36 | - name: http
37 | port: 80
38 | selector:
39 | app.kubernetes.io/name: whoami
40 | app.kubernetes.io/instance: whoami
41 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/bfenetworks/ingress-bfe
2 |
3 | go 1.16
4 |
5 | require (
6 | github.com/bfenetworks/bfe v1.5.0
7 | github.com/jwangsadinata/go-multimap v0.0.0-20190620162914-c29f3d7f33b6
8 | k8s.io/api v0.21.2
9 | k8s.io/apimachinery v0.21.2
10 | k8s.io/client-go v0.21.2
11 | k8s.io/klog/v2 v2.9.0 //indirect
12 | sigs.k8s.io/controller-runtime v0.9.2
13 | )
14 |
--------------------------------------------------------------------------------
/internal/bfeConfig/annotations/annotation.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package annotations
15 |
16 | import (
17 | netv1beta1 "k8s.io/api/networking/v1beta1"
18 | )
19 |
20 | const (
21 | BfeAnnotationPrefix = "bfe.ingress.kubernetes.io/"
22 |
23 | IngressClassKey = netv1beta1.AnnotationIngressClass
24 | IsDefaultIngressClass = netv1beta1.AnnotationIsDefaultIngressClass
25 | )
26 |
--------------------------------------------------------------------------------
/internal/bfeConfig/annotations/balance.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package annotations
15 |
16 | import (
17 | "encoding/json"
18 | "fmt"
19 | )
20 |
21 | const (
22 | WeightKey = "balance.weight"
23 | WeightAnnotation = BfeAnnotationPrefix + WeightKey
24 | )
25 |
26 | // ServicesWeight define struct of annotation "balance.weight"
27 | // example: {"service": {"service1":80, "service2":20}}
28 | type ServicesWeight map[string]int
29 | type Balance map[string]ServicesWeight
30 |
31 | // GetBalance parse annotation "balance.weight"
32 | func GetBalance(annotations map[string]string) (Balance, error) {
33 | value, ok := annotations[WeightAnnotation]
34 | if !ok {
35 | return nil, nil
36 | }
37 |
38 | var lb = make(Balance)
39 | err := json.Unmarshal([]byte(value), &lb)
40 | if err != nil {
41 | return nil, fmt.Errorf("annotation %s is illegal, error: %s", WeightAnnotation, err)
42 | }
43 |
44 | // check whether weight sum > 0
45 | for _, services := range lb {
46 | sum := 0
47 | for _, weight := range services {
48 | if weight < 0 {
49 | return nil, fmt.Errorf("weight of load balance service should >= 0")
50 | }
51 | sum += weight
52 | }
53 | if sum == 0 {
54 | return nil, fmt.Errorf("sum of all load balance service weight should > 0")
55 | }
56 | }
57 | return lb, nil
58 | }
59 |
--------------------------------------------------------------------------------
/internal/bfeConfig/annotations/priority.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package annotations
15 |
16 | const (
17 | PriorityBasic = 10
18 | PriorityHeader = 20
19 | PriorityCookie = 30
20 | PriorityCookieHeader = 40
21 | )
22 |
23 | func Priority(annotations map[string]string) int {
24 | _, ok1 := annotations[CookieAnnotation]
25 | _, ok2 := annotations[HeaderAnnotation]
26 |
27 | if ok1 && ok2 {
28 | return PriorityCookieHeader
29 | } else if ok1 {
30 | return PriorityCookie
31 | } else if ok2 {
32 | return PriorityHeader
33 | } else {
34 | return PriorityBasic
35 | }
36 | }
37 |
38 | func Equal(annotations1, annotations2 map[string]string) bool {
39 | if annotations1 == nil && annotations2 == nil {
40 | return true
41 | }
42 |
43 | return annotations1[CookieAnnotation] == annotations2[CookieAnnotation] &&
44 | annotations1[HeaderAnnotation] == annotations2[HeaderAnnotation]
45 | }
46 |
--------------------------------------------------------------------------------
/internal/bfeConfig/annotations/redirect.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package annotations
16 |
17 | import (
18 | "errors"
19 | "strconv"
20 | )
21 |
22 | const (
23 | redirectAnnotationPrefix = BfeAnnotationPrefix + "redirect."
24 | defaultRedirectResponseStatusCode = 302
25 | )
26 |
27 | // the annotations related to how to set the location in the redirection response's header
28 | const (
29 | RedirectURLSetAnnotation = redirectAnnotationPrefix + "url-set"
30 | RedirectURLFromQueryAnnotation = redirectAnnotationPrefix + "url-from-query"
31 | RedirectURLPrefixAddAnnotation = redirectAnnotationPrefix + "url-prefix-add"
32 | RedirectSchemeSetSetAnnotation = redirectAnnotationPrefix + "scheme-set"
33 | )
34 |
35 | // RedirectResponseStatusAnnotation is used to set the status code of the redirection response manually
36 | const RedirectResponseStatusAnnotation = redirectAnnotationPrefix + "response-status"
37 |
38 | // GetRedirectAction try to parse the cmd and the param of the redirection action from the annotations
39 | func GetRedirectAction(annotations map[string]string) (cmd, param string, err error) {
40 | switch {
41 | case annotations[RedirectURLSetAnnotation] != "":
42 | cmd, param = "URL_SET", annotations[RedirectURLSetAnnotation]
43 |
44 | case annotations[RedirectURLFromQueryAnnotation] != "":
45 | cmd, param = "URL_FROM_QUERY", annotations[RedirectURLFromQueryAnnotation]
46 |
47 | case annotations[RedirectURLPrefixAddAnnotation] != "":
48 | cmd, param = "URL_PREFIX_ADD", annotations[RedirectURLPrefixAddAnnotation]
49 |
50 | case annotations[RedirectSchemeSetSetAnnotation] != "":
51 | cmd, param = "SCHEME_SET", annotations[RedirectSchemeSetSetAnnotation]
52 | }
53 | return
54 | }
55 |
56 | func GetRedirectStatusCode(annotations map[string]string) (int, error) {
57 | statusCodeStr := annotations[RedirectResponseStatusAnnotation]
58 | if statusCodeStr == "" {
59 | return defaultRedirectResponseStatusCode, nil
60 | }
61 |
62 | statusCodeInt64, err := strconv.ParseInt(statusCodeStr, 10, 64)
63 | if err != nil {
64 | return 0, err
65 | }
66 | if err != nil {
67 | return 0, errors.New("the annotation %s should be a integer")
68 | }
69 | return int(statusCodeInt64), nil
70 | }
71 |
--------------------------------------------------------------------------------
/internal/bfeConfig/annotations/router.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package annotations
15 |
16 | import (
17 | "fmt"
18 | "strings"
19 | )
20 |
21 | const (
22 | CookieKey = "router.cookie"
23 | HeaderKey = "router.header"
24 |
25 | CookieAnnotation = BfeAnnotationPrefix + CookieKey
26 | HeaderAnnotation = BfeAnnotationPrefix + HeaderKey
27 | )
28 |
29 | func GetRouteExpression(annotations map[string]string) (string, error) {
30 | var primitive1 string
31 | var err error
32 | if primitive1, err = cookiePrimitive(annotations[CookieAnnotation]); err != nil {
33 | return "", err
34 | }
35 |
36 | var primitive2 string
37 | if primitive2, err = headerPrimitive(annotations[HeaderAnnotation]); err != nil {
38 | return "", err
39 | }
40 |
41 | if len(primitive1) > 0 && len(primitive2) > 0 {
42 | return primitive1 + "&&" + primitive2, nil
43 | }
44 | if len(primitive1) > 0 {
45 | return primitive1, nil
46 | }
47 | if len(primitive2) > 0 {
48 | return primitive2, nil
49 | }
50 | return "", nil
51 | }
52 |
53 | // cookiePrimitive generates bfe condition primitive for cookie match
54 | func cookiePrimitive(cookie string) (string, error) {
55 | if len(cookie) == 0 {
56 | return "", nil
57 | }
58 | index := strings.Index(cookie, ":")
59 | if index == -1 || index == len(cookie)-1 {
60 | return "", fmt.Errorf("cookie annotation[%s] is illegal", cookie)
61 | }
62 |
63 | con := fmt.Sprintf("req_cookie_value_in(\"%s\", \"%v\", false)", strings.TrimSpace(cookie[:index]), strings.TrimSpace(cookie[index+1:]))
64 | return con, nil
65 |
66 | }
67 |
68 | // cookiePrimitive generates bfe condition primitive for header match
69 | func headerPrimitive(header string) (string, error) {
70 | if len(header) == 0 {
71 | return "", nil
72 | }
73 | index := strings.Index(header, ":")
74 | if index == -1 || index == len(header)-1 {
75 | return "", fmt.Errorf("header annotation[%s] is illegal", header)
76 | }
77 |
78 | con := fmt.Sprintf("req_header_value_in(\"%s\", \"%v\", false)", strings.TrimSpace(header[:index]), strings.TrimSpace(header[index+1:]))
79 | return con, nil
80 | }
81 |
--------------------------------------------------------------------------------
/internal/bfeConfig/annotations/status.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package annotations
15 |
16 | import (
17 | "encoding/json"
18 | )
19 |
20 | var (
21 | StatusKey = "bfe-ingress-status"
22 | StatusAnnotationKey = BfeAnnotationPrefix + StatusKey
23 | )
24 |
25 | type statusMsg struct {
26 | Status string `json:"status"`
27 | Message string `json:"message,omitempty"`
28 | }
29 |
30 | func GenErrorMsg(err error) string {
31 | var status = statusMsg{}
32 |
33 | if err == nil {
34 | status.Status = "success"
35 | } else {
36 | status.Status = "error"
37 | status.Message = err.Error()
38 | }
39 |
40 | jsons, _ := json.Marshal(status)
41 | return string(jsons)
42 | }
43 |
44 | // CompareStatus check errMsg with status, return 0 if equal
45 | func CompareStatus(e error, status string) int {
46 | if len(status) == 0 {
47 | return 1
48 | }
49 |
50 | s := &statusMsg{}
51 | if err := json.Unmarshal([]byte(status), s); err != nil {
52 | return 1
53 | }
54 |
55 | if e == nil && s.Status == "success" {
56 | return 0
57 | }
58 |
59 | if e != nil && s.Status == "error" && s.Message == e.Error() {
60 | return 0
61 | }
62 |
63 | return 1
64 | }
65 |
--------------------------------------------------------------------------------
/internal/bfeConfig/configs/cache/baseRule.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package cache
16 |
17 | import (
18 | "fmt"
19 | "strings"
20 | "time"
21 |
22 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/annotations"
23 | )
24 |
25 | type BaseRule struct {
26 | Ingress string
27 | Host string
28 | Path string
29 | Annotations map[string]string
30 | CreateTime time.Time
31 | }
32 |
33 | func (rule BaseRule) GetIngress() string {
34 | return rule.Ingress
35 | }
36 |
37 | func (rule BaseRule) GetHost() string {
38 | return rule.Host
39 | }
40 |
41 | func (rule BaseRule) GetPath() string {
42 | return rule.Path
43 | }
44 |
45 | func (rule BaseRule) GetAnnotations() map[string]string {
46 | return rule.Annotations
47 | }
48 |
49 | func (rule BaseRule) GetCreateTime() time.Time {
50 | return rule.CreateTime
51 | }
52 |
53 | func (rule BaseRule) GetCond() (string, error) {
54 | return buildCondition(rule.Host, rule.Path, rule.Annotations)
55 | }
56 |
57 | func buildCondition(host string, path string, annots map[string]string) (string, error) {
58 | var statement []string
59 |
60 | primitive, err := hostPrimitive(host)
61 | if err != nil {
62 | return "", err
63 | }
64 | if len(primitive) > 0 {
65 | statement = append(statement, primitive)
66 | }
67 |
68 | primitive, err = pathPrimitive(path)
69 | if err != nil {
70 | return "", err
71 | }
72 | if len(primitive) > 0 {
73 | statement = append(statement, primitive)
74 | }
75 |
76 | primitive, err = annotations.GetRouteExpression(annots)
77 | if err != nil {
78 | return "", err
79 | }
80 | if len(primitive) > 0 {
81 | statement = append(statement, primitive)
82 | }
83 |
84 | return strings.Join(statement, "&&"), nil
85 | }
86 |
87 | // hostPrimitive builds host primitive in condition
88 | func hostPrimitive(host string) (string, error) {
89 | if len(host) == 0 || host == "*" {
90 | return "", nil
91 | }
92 |
93 | if strings.HasPrefix(host, "*.") {
94 | dn := host[2:]
95 | dn = strings.ReplaceAll(dn, ".", "\\.")
96 | return fmt.Sprintf(`req_host_regmatch("(?i)^[^\.]+%s")`, dn), nil
97 | }
98 | return fmt.Sprintf(`req_host_in("%s")`, host), nil
99 | }
100 |
101 | // pathPrimitive builds path primitive in condition
102 | func pathPrimitive(path string) (string, error) {
103 | if len(path) == 0 || path == "*" {
104 | return "", nil // no restriction
105 | }
106 | if path[len(path)-1] == '*' {
107 | return fmt.Sprintf(`req_path_element_prefix_in("%s", false)`, path[:len(path)-1]), nil
108 | }
109 | return fmt.Sprintf(`req_path_in("%s", false)`, path), nil
110 | }
111 |
--------------------------------------------------------------------------------
/internal/bfeConfig/configs/log/log.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package log
16 |
17 | import "sigs.k8s.io/controller-runtime"
18 |
19 | var (
20 | Log = controllerruntime.Log.WithName("configBuilder")
21 | )
22 |
--------------------------------------------------------------------------------
/internal/bfeConfig/configs/modules/module.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package modules
16 |
17 | import (
18 | netv1 "k8s.io/api/networking/v1"
19 |
20 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/configs/modules/redirect"
21 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/configs/modules/rewrite"
22 | )
23 |
24 | // BFEModuleConfig is an abstraction of the BFE module configuration.
25 | // The ConfigBuilder will call the corresponding function in this interface when update/delete ingresses or reload the BFE Engine.
26 | type BFEModuleConfig interface {
27 | // UpdateIngress uses the ingress to update the BFEModuleConfig
28 | UpdateIngress(ingress *netv1.Ingress) error
29 |
30 | // DeleteIngress delete everything related to the ingress from the BFEModuleConfig
31 | DeleteIngress(ingressNamespace, ingressName string)
32 |
33 | // Reload dumps the data in the BFEModuleConfig to the corresponding BFE conf files on the disk
34 | Reload() error
35 |
36 | // Name returns the name of the BFEModuleConfig
37 | Name() string
38 | }
39 |
40 | func InitBFEModules(version string) []BFEModuleConfig {
41 | var modules []BFEModuleConfig
42 | // mod_redirect
43 | modules = append(modules, redirect.NewRedirectConfig(version))
44 | modules = append(modules, rewrite.NewRewriteConfig(version))
45 | return modules
46 | }
47 |
--------------------------------------------------------------------------------
/internal/bfeConfig/configs/modules/redirect/cache.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package redirect
16 |
17 | import (
18 | "github.com/bfenetworks/bfe/bfe_modules/mod_redirect"
19 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/annotations"
20 | netv1 "k8s.io/api/networking/v1"
21 |
22 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/configs/cache"
23 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/util"
24 | )
25 |
26 | type redirectRule struct {
27 | *cache.BaseRule
28 | // statusCode is the response status code of redirect
29 | statusCode int
30 | // action is the redirect action. Refer to https://www.bfe-networks.net/en_us/modules/mod_redirect/mod_redirect/.
31 | action *mod_redirect.ActionFileList
32 | }
33 |
34 | type redirectRuleCache struct {
35 | *cache.BaseCache
36 | }
37 |
38 | func newRedirectRuleCache(version string) *redirectRuleCache {
39 | return &redirectRuleCache{
40 | BaseCache: cache.NewBaseCache(version),
41 | }
42 | }
43 |
44 | func (c redirectRuleCache) UpdateByIngress(ingress *netv1.Ingress) error {
45 | if len(ingress.Spec.Rules) == 0 {
46 | return nil
47 | }
48 |
49 | cmd, param, err := parseRedirectActionFromAnnotations(ingress.Annotations)
50 | if err != nil {
51 | return err
52 | }
53 | statusCode, err := annotations.GetRedirectStatusCode(ingress.Annotations)
54 | if err != nil {
55 | return err
56 | }
57 | return c.BaseCache.UpdateByIngressFramework(
58 | ingress,
59 | func(ingress *netv1.Ingress, host, path string, _ netv1.HTTPIngressPath) (cache.Rule, error) {
60 | // preCheck
61 | if err := checkAction(cmd, param); err != nil {
62 | return nil, err
63 | }
64 | if err := checkStatusCode(statusCode); err != nil {
65 | return nil, err
66 | }
67 |
68 | action := &mod_redirect.ActionFileList{mod_redirect.ActionFile{
69 | Cmd: &cmd,
70 | Params: []string{param},
71 | }}
72 | if err = mod_redirect.ActionFileListCheck(action); err != nil {
73 | return nil, err
74 | }
75 | return &redirectRule{
76 | BaseRule: cache.NewBaseRule(
77 | util.NamespacedName(ingress.Namespace, ingress.Name),
78 | host,
79 | path,
80 | ingress.Annotations,
81 | ingress.CreationTimestamp.Time,
82 | ),
83 | statusCode: statusCode,
84 | action: action,
85 | }, nil
86 | },
87 | func() (bool, error) {
88 | return cmd != "", err
89 | },
90 | nil,
91 | )
92 | }
93 |
--------------------------------------------------------------------------------
/internal/bfeConfig/configs/routeRuleCache.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package configs
16 |
17 | import (
18 | "sort"
19 | "time"
20 |
21 | "github.com/bfenetworks/bfe/bfe_config/bfe_route_conf/route_rule_conf"
22 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/util"
23 | netv1 "k8s.io/api/networking/v1"
24 |
25 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/annotations"
26 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/configs/cache"
27 | )
28 |
29 | type routeRule struct {
30 | Cluster string
31 | *cache.BaseRule
32 | }
33 |
34 | type RouteRuleCache struct {
35 | *cache.BaseCache
36 | }
37 |
38 | func newRouteRuleCache(version string) *RouteRuleCache {
39 | return &RouteRuleCache{
40 | BaseCache: cache.NewBaseCache(version),
41 | }
42 | }
43 |
44 | func newRouteRule(ingress string, host string, path string, annots map[string]string, cluster string, time time.Time) *routeRule {
45 | return &routeRule{
46 | BaseRule: cache.NewBaseRule(
47 | ingress,
48 | host,
49 | path,
50 | annots,
51 | time,
52 | ),
53 | Cluster: cluster,
54 | }
55 | }
56 |
57 | func (c *RouteRuleCache) getRouteRules() (basicRuleList []*routeRule, advancedRuleList []*routeRule) {
58 | httpRules := c.BaseRules
59 | for _, paths := range httpRules.RuleMap {
60 | for _, ruleList := range paths {
61 | if len(ruleList) == 0 {
62 | continue
63 | }
64 |
65 | // add host+path rule to basic rule list
66 | if len(ruleList) == 1 && annotations.Priority(ruleList[0].GetAnnotations()) == annotations.PriorityBasic {
67 | basicRuleList = append(basicRuleList, ruleList[0].(*routeRule))
68 | continue
69 | }
70 | // add a fake basicRule,cluster=ADVANCED_MODE
71 | newRule := *ruleList[0].(*routeRule)
72 | newRule.Cluster = route_rule_conf.AdvancedMode
73 | basicRuleList = append(basicRuleList, &newRule)
74 |
75 | // add advanced rule
76 | for _, rule := range ruleList {
77 | advancedRuleList = append(advancedRuleList, rule.(*routeRule))
78 | }
79 | }
80 | }
81 |
82 | // host: exact match over wildcard match
83 | // path: long path over short path
84 | sort.SliceStable(advancedRuleList, func(i, j int) bool {
85 | return cache.CompareRule(advancedRuleList[i], advancedRuleList[j])
86 | })
87 |
88 | return
89 | }
90 |
91 | func (c *RouteRuleCache) UpdateByIngress(ingress *netv1.Ingress) error {
92 | return c.BaseCache.UpdateByIngressFramework(
93 | ingress,
94 | func(ingress *netv1.Ingress, host, path string, httpPath netv1.HTTPIngressPath) (cache.Rule, error) {
95 | ingressName := util.NamespacedName(ingress.Namespace, ingress.Name)
96 | return newRouteRule(
97 | ingressName,
98 | host,
99 | path,
100 | ingress.Annotations,
101 | util.ClusterName(ingressName, httpPath.Backend.Service),
102 | ingress.CreationTimestamp.Time,
103 | ), nil
104 | },
105 | nil,
106 | nil,
107 | )
108 | }
109 |
--------------------------------------------------------------------------------
/internal/bfeConfig/util/io.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package util
15 |
16 | import (
17 | "encoding/json"
18 | "fmt"
19 | "io"
20 | "io/ioutil"
21 | "net/http"
22 | "os"
23 | "path/filepath"
24 |
25 | "github.com/bfenetworks/ingress-bfe/internal/option"
26 | )
27 |
28 | func DumpBfeConf(configFile string, object interface{}) error {
29 | buf, err := json.MarshalIndent(object, "", " ")
30 | if err != nil {
31 | return fmt.Errorf("config json marshal err %s", err)
32 | }
33 | return DumpFile(configFile, buf)
34 | }
35 |
36 | func DumpFile(filename string, data []byte) error {
37 | name := option.Opts.Ingress.ConfigPath + filename
38 | filePath := filepath.Dir(name)
39 | if _, err := os.Stat(filePath); os.IsNotExist(err) {
40 | os.MkdirAll(filePath, option.Opts.Ingress.FilePerm)
41 | }
42 |
43 | return ioutil.WriteFile(name, data, option.Opts.Ingress.FilePerm)
44 | }
45 |
46 | func DeleteFile(filename string) {
47 | name := option.Opts.Ingress.ConfigPath + filename
48 | os.Remove(name)
49 | }
50 |
51 | // ReloadBfe triggers bfe process to reload new config file through bfe monitor port
52 | func ReloadBfe(configName string) error {
53 | url := option.Opts.Ingress.ReloadUrl + configName
54 | res, err := http.Get(url)
55 | if err != nil {
56 | return err
57 | }
58 | defer res.Body.Close()
59 |
60 | if res.StatusCode == http.StatusOK {
61 | return nil
62 | }
63 |
64 | failReason, err := ioutil.ReadAll(io.LimitReader(res.Body, 1024))
65 | if err != nil {
66 | return err
67 | }
68 |
69 | return fmt.Errorf("fail to reload: %s", failReason)
70 | }
71 |
--------------------------------------------------------------------------------
/internal/bfeConfig/util/name.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package util
15 |
16 | import (
17 | "fmt"
18 | "strconv"
19 | "strings"
20 |
21 | "github.com/bfenetworks/ingress-bfe/internal/option"
22 | netv1 "k8s.io/api/networking/v1"
23 | "k8s.io/apimachinery/pkg/types"
24 | )
25 |
26 | func ClusterName(ingressName string, backend *netv1.IngressServiceBackend) string {
27 | port := backend.Port.Name
28 | if backend.Port.Number > 0 {
29 | port = fmt.Sprintf("%d", backend.Port.Number)
30 | }
31 | return fmt.Sprintf("%s_%s_%s", ingressName, backend.Name, port)
32 | }
33 |
34 | // DefaultClusterName returns a default cluster for default backend
35 | func DefaultClusterName() string {
36 | ingress := "__defaultCluster__"
37 | return fmt.Sprintf("%s_%s_%d", ingress, option.Opts.Ingress.DefaultBackend, 0)
38 | }
39 |
40 | func ParsePort(clusterName string) netv1.ServiceBackendPort {
41 | port := netv1.ServiceBackendPort{}
42 | index := strings.LastIndexByte(clusterName, '_')
43 | if index < 0 {
44 | return port
45 | }
46 | portStr := clusterName[index+1:]
47 |
48 | if i, err := strconv.Atoi(portStr); err == nil {
49 | port.Number = int32(i)
50 | } else {
51 | port.Name = portStr
52 | }
53 | return port
54 | }
55 |
56 | func NamespacedName(namespace, name string) string {
57 | return types.NamespacedName{
58 | Namespace: namespace,
59 | Name: name,
60 | }.String()
61 | }
62 |
63 | func SplitNamespacedName(namespacedName string) (namespace, name string) {
64 | names := strings.Split(namespacedName, "/")
65 | if len(names) != 2 {
66 | return "", ""
67 | }
68 | return names[0], names[1]
69 | }
70 |
--------------------------------------------------------------------------------
/internal/bfeConfig/util/version.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | package util
15 |
16 | import (
17 | "time"
18 | )
19 |
20 | func NewVersion() string {
21 | return time.Now().Format(time.RFC3339Nano)
22 | }
23 |
--------------------------------------------------------------------------------
/internal/controllers/event/events.go:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License");
2 | // you may not use this file except in compliance with the License.
3 | // You may obtain a copy of the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS,
9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | // See the License for the specific language governing permissions and
11 | // limitations under the License.
12 |
13 | package event
14 |
15 | // event reason
16 | const (
17 | SyncFailed = "SyncFailed"
18 | SyncSucceed = "SyncSucceed"
19 | )
20 |
--------------------------------------------------------------------------------
/internal/controllers/filter/ingressClass.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package filter
16 |
17 | import (
18 | "context"
19 | "strings"
20 |
21 | netv1 "k8s.io/api/networking/v1"
22 | netv1beta1 "k8s.io/api/networking/v1beta1"
23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 | "sigs.k8s.io/controller-runtime/pkg/client"
25 |
26 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/annotations"
27 | "github.com/bfenetworks/ingress-bfe/internal/option"
28 | )
29 |
30 | func IngressClassFilter(ctx context.Context, r client.Reader, annots map[string]string, ingressClassName *string) bool {
31 | if annots[annotations.IngressClassKey] == option.Opts.Ingress.IngressClass {
32 | return true
33 | }
34 |
35 | classListV1 := &netv1.IngressClassList{}
36 | err := r.List(ctx, classListV1)
37 | if err == nil {
38 | for _, class := range classListV1.Items {
39 | if class.Spec.Controller != option.Opts.Ingress.ControllerName {
40 | continue
41 | }
42 | if matchIngressClass(ingressClassName, &class) {
43 | return true
44 | }
45 | }
46 | }
47 |
48 | classListV1Beta1 := &netv1beta1.IngressClassList{}
49 | err = r.List(ctx, classListV1Beta1)
50 | if err != nil {
51 | return false
52 | }
53 | for _, classV1Beta1 := range classListV1Beta1.Items {
54 | if classV1Beta1.Spec.Controller != option.Opts.Ingress.ControllerName {
55 | continue
56 | }
57 | if matchIngressClass(ingressClassName, &classV1Beta1) {
58 | return true
59 | }
60 | }
61 |
62 | return false
63 | }
64 |
65 | // matchIngressClass matches for specific or default ingress class
66 | // Params:
67 | // targetCls: target ingress class name
68 | // if non-nil, matches ingress class with the same name
69 | // if nil, matches default ingress class
70 | func matchIngressClass(targetCls *string, testCls v1.Object) bool {
71 | // specific ingress class
72 | if targetCls != nil {
73 | return *targetCls == testCls.GetName()
74 | }
75 |
76 | // default ingress class
77 | annots := testCls.GetAnnotations()
78 | return strings.EqualFold(annots[annotations.IsDefaultIngressClass], "true")
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/internal/controllers/filter/ingressClass_test.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package filter
16 |
17 | import (
18 | "testing"
19 |
20 | netv1 "k8s.io/api/networking/v1"
21 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22 | "k8s.io/utils/pointer"
23 |
24 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig/annotations"
25 | )
26 |
27 | func Test_matchIngressClass(t *testing.T) {
28 | type args struct {
29 | targetCls *string
30 | testCls v1.Object
31 | }
32 | tests := []struct {
33 | name string
34 | args args
35 | want bool
36 | }{
37 | {
38 | name: "match specific",
39 | args: args{
40 | targetCls: pointer.String("bfe"),
41 | testCls: &netv1.IngressClass{
42 | ObjectMeta: v1.ObjectMeta{
43 | Name: "bfe",
44 | },
45 | },
46 | },
47 | want: true,
48 | },
49 | {
50 | name: "mismatch specific",
51 | args: args{
52 | targetCls: pointer.String("bfe"),
53 | testCls: &netv1.IngressClass{
54 | ObjectMeta: v1.ObjectMeta{
55 | Name: "other",
56 | },
57 | },
58 | },
59 | want: false,
60 | },
61 | {
62 | name: "match default",
63 | args: args{
64 | targetCls: nil,
65 | testCls: &netv1.IngressClass{
66 | ObjectMeta: v1.ObjectMeta{
67 | Annotations: map[string]string{
68 | annotations.IsDefaultIngressClass: "True",
69 | },
70 | },
71 | },
72 | },
73 | want: true,
74 | },
75 | {
76 | name: "mismatch default",
77 | args: args{
78 | targetCls: nil,
79 | testCls: &netv1.IngressClass{},
80 | },
81 | want: false,
82 | },
83 | }
84 | for _, tt := range tests {
85 | t.Run(tt.name, func(t *testing.T) {
86 | if got := matchIngressClass(tt.args.targetCls, tt.args.testCls); got != tt.want {
87 | t.Errorf("matchIngressClass() = %v, want %v", got, tt.want)
88 | }
89 | })
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/internal/controllers/filter/namespace.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package filter
16 |
17 | import (
18 | corev1 "k8s.io/api/core/v1"
19 | "sigs.k8s.io/controller-runtime/pkg/client"
20 | "sigs.k8s.io/controller-runtime/pkg/predicate"
21 |
22 | "github.com/bfenetworks/ingress-bfe/internal/option"
23 | )
24 |
25 | func NamespaceFilter() predicate.Funcs {
26 | funcs := predicate.NewPredicateFuncs(func(obj client.Object) bool {
27 | if len(option.Opts.NamespaceList) == 1 && option.Opts.NamespaceList[0] == corev1.NamespaceAll {
28 | return true
29 | }
30 | for _, ns := range option.Opts.NamespaceList {
31 | if ns == obj.GetNamespace() {
32 | return true
33 | }
34 | }
35 | return false
36 | })
37 |
38 | return funcs
39 | }
40 |
--------------------------------------------------------------------------------
/internal/controllers/ingress/secret_controller.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package ingress
16 |
17 | import (
18 | "context"
19 | "fmt"
20 |
21 | corev1 "k8s.io/api/core/v1"
22 | "k8s.io/apimachinery/pkg/runtime"
23 | ctrl "sigs.k8s.io/controller-runtime"
24 | "sigs.k8s.io/controller-runtime/pkg/builder"
25 | "sigs.k8s.io/controller-runtime/pkg/client"
26 | "sigs.k8s.io/controller-runtime/pkg/log"
27 | "sigs.k8s.io/controller-runtime/pkg/manager"
28 |
29 | "github.com/bfenetworks/ingress-bfe/internal/bfeConfig"
30 | "github.com/bfenetworks/ingress-bfe/internal/controllers/filter"
31 | )
32 |
33 | func AddSecretController(mgr manager.Manager, cb *bfeConfig.ConfigBuilder) error {
34 | reconciler := newSecretReconciler(mgr, cb)
35 | if err := reconciler.setupWithManager(mgr); err != nil {
36 | return fmt.Errorf("unable to create ingress controller")
37 | }
38 |
39 | return nil
40 | }
41 |
42 | // SecretReconciler reconciles a Secret object
43 | type SecretReconciler struct {
44 | BfeConfigBuilder *bfeConfig.ConfigBuilder
45 |
46 | client.Client
47 | Scheme *runtime.Scheme
48 | }
49 |
50 | func newSecretReconciler(mgr manager.Manager, cb *bfeConfig.ConfigBuilder) *SecretReconciler {
51 | return &SecretReconciler{
52 | BfeConfigBuilder: cb,
53 | Client: mgr.GetClient(),
54 | Scheme: mgr.GetScheme(),
55 | }
56 | }
57 |
58 | func (r *SecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
59 | log := log.FromContext(ctx)
60 | log.V(1).Info("reconciling Secret", "api version", "corev1")
61 |
62 | secret := &corev1.Secret{}
63 | err := r.Get(ctx, client.ObjectKey{
64 | Namespace: req.Namespace,
65 | Name: req.Name,
66 | }, secret)
67 | if err != nil {
68 | return ctrl.Result{}, nil
69 | }
70 |
71 | r.BfeConfigBuilder.UpdateSecret(secret)
72 |
73 | return ctrl.Result{}, nil
74 | }
75 |
76 | // setupWithManager sets up the controller with the Manager.
77 | func (r *SecretReconciler) setupWithManager(mgr ctrl.Manager) error {
78 | return ctrl.NewControllerManagedBy(mgr).
79 | For(&corev1.Secret{}, builder.WithPredicates(filter.NamespaceFilter())).
80 | Complete(r)
81 | }
82 |
--------------------------------------------------------------------------------
/internal/option/ingress/options.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package ingress
16 |
17 | import (
18 | "fmt"
19 | "os"
20 | "path/filepath"
21 | "strings"
22 | "time"
23 |
24 | "k8s.io/apimachinery/pkg/types"
25 | )
26 |
27 | const (
28 | enableIngress = true
29 |
30 | configPath = "/bfe/conf/"
31 | bfeBinary = "/bfe/bin/bfe"
32 | reloadAddr = "localhost:8421"
33 | reloadInterval = 3 * time.Second
34 | reloadUrlPrefix = "http://%s/reload/"
35 |
36 | filePerm os.FileMode = 0744
37 |
38 | // used in ingress annotation as value of key kubernetes.io/ingress.class
39 | ingressClassName = "bfe"
40 |
41 | // used in IngressClass resource as value of controller
42 | controllerName = "bfe-networks.com/ingress-controller"
43 |
44 | // default backend
45 | defaultBackend = ""
46 | )
47 |
48 | type Options struct {
49 | EnableIngress bool
50 | IngressClass string
51 | ControllerName string
52 | ReloadAddr string
53 | ReloadUrl string
54 | BfeBinary string
55 | ConfigPath string
56 | FilePerm os.FileMode
57 | ReloadInterval time.Duration
58 | DefaultBackend string
59 | }
60 |
61 | func NewOptions() *Options {
62 | return &Options{
63 | EnableIngress: enableIngress,
64 | IngressClass: ingressClassName,
65 | ControllerName: controllerName,
66 | ReloadAddr: reloadAddr,
67 | BfeBinary: bfeBinary,
68 | ConfigPath: configPath,
69 | FilePerm: filePerm,
70 | ReloadInterval: reloadInterval,
71 | DefaultBackend: defaultBackend,
72 | }
73 | }
74 |
75 | func (opts *Options) Check() error {
76 | if !opts.EnableIngress {
77 | return nil
78 | }
79 |
80 | if len(opts.DefaultBackend) > 0 {
81 | names := strings.Split(opts.DefaultBackend, string(types.Separator))
82 | if len(names) != 2 {
83 | return fmt.Errorf("invalid command line argument default-backend: %s", opts.DefaultBackend)
84 | }
85 | }
86 | if len(opts.BfeBinary) > 0 {
87 | opts.ConfigPath = filepath.Dir(filepath.Dir(opts.BfeBinary)) + "/conf"
88 | }
89 |
90 | if !strings.HasSuffix(opts.ConfigPath, "/") {
91 | opts.ConfigPath = opts.ConfigPath + "/"
92 | }
93 |
94 | opts.ReloadUrl = fmt.Sprintf(reloadUrlPrefix, opts.ReloadAddr)
95 | return nil
96 | }
97 |
--------------------------------------------------------------------------------
/internal/option/options.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021 The BFE Authors.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package option
16 |
17 | import (
18 | "strings"
19 |
20 | corev1 "k8s.io/api/core/v1"
21 |
22 | "github.com/bfenetworks/ingress-bfe/internal/option/ingress"
23 | )
24 |
25 | const (
26 | ClusterName = "default"
27 | MetricsBindAddress = ":9080"
28 | HealthProbeBindAddress = ":9081"
29 | )
30 |
31 | type Options struct {
32 | ClusterName string
33 |
34 | Namespaces string
35 | NamespaceList []string
36 | MetricsAddr string
37 | HealthProbeAddr string
38 |
39 | Ingress *ingress.Options
40 | }
41 |
42 | var (
43 | Opts *Options
44 | )
45 |
46 | func NewOptions() *Options {
47 | return &Options{
48 | ClusterName: ClusterName,
49 | Namespaces: corev1.NamespaceAll,
50 | MetricsAddr: MetricsBindAddress,
51 | HealthProbeAddr: HealthProbeBindAddress,
52 | Ingress: ingress.NewOptions(),
53 | }
54 | }
55 |
56 | func SetOptions(option *Options) error {
57 | if err := option.Ingress.Check(); err != nil {
58 | return err
59 | }
60 |
61 | Opts = option
62 | Opts.NamespaceList = strings.Split(Opts.Namespaces, ",")
63 |
64 | return nil
65 | }
66 |
--------------------------------------------------------------------------------
/scripts/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2021 The BFE Authors
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | set -e
17 | if [ $# -lt 2 ]; then
18 | echo "error: number of argument should >= 2"
19 | exit 1
20 | fi
21 |
22 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
23 |
24 | CTL_BIN=$1
25 | BFE_BIN=$2
26 |
27 | BFE_NAME="$(basename $BFE_BIN)"
28 | BFE_ROOT_DIR="$(cd "$(dirname "$BFE_BIN")/.." && pwd -P)"
29 | CONF_DIR="$BFE_ROOT_DIR/conf"
30 | BFE_BIN_DIR="$BFE_ROOT_DIR/bin"
31 |
32 | shift 2
33 | ARGS="$@ -c $CONF_DIR "
34 | if [ -n "$INGRESS_LISTEN_NAMESPACE" ]; then
35 | ARGS=$ARGS"-n $INGRESS_LISTEN_NAMESPACE"
36 | fi
37 |
38 | cd ${BFE_BIN_DIR} && ./${BFE_NAME} -c ../conf -l ../log &
39 | sleep 1
40 | pgrep ${BFE_NAME}
41 | if [ $? -ne 0 ]; then
42 | exit 1
43 | fi
44 |
45 | ${CTL_BIN} $ARGS
46 |
--------------------------------------------------------------------------------
/test/e2e/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Build
16 | FROM golang:1.16-alpine3.14 as builder
17 |
18 | WORKDIR /go/src/github.com/bfenetworks/ingress-bfe
19 | # Copy the Go Modules manifests
20 | COPY go.mod go.mod
21 | COPY go.sum go.sum
22 | # cache deps before building and copying source so that we don't need to re-download as much
23 | # and so that source changes don't invalidate our downloaded layer
24 | RUN go mod download
25 |
26 | # Copy the go source
27 | COPY . /go/src/github.com/bfenetworks/ingress-bfe
28 |
29 | # Build
30 | RUN make e2e_test
31 |
32 | FROM alpine3.14
33 |
34 | ENV RESULTS_DIR="/tmp/results"
35 | ENV WAIT_FOR_STATUS_TIMEOUT="5m"
36 | ENV TEST_TIMEOUT="5m"
37 |
38 | COPY --from=builder /go/src/github.com/bfenetworks/ingress-bfe/e2e_test /
39 |
40 | COPY features /features
41 | COPY run.sh /
42 |
43 | CMD [ "/run.sh" ]
44 |
--------------------------------------------------------------------------------
/test/e2e/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | .DEFAULT_GOAL:=help
16 |
17 | MKDIR_P := mkdir -p
18 | RM_F := rm -rf
19 |
20 |
21 | PROGRAMS := \
22 | e2e_test
23 |
24 | TAG ?= 0.0.1
25 |
26 | REGISTRY ?= local
27 |
28 | build: $(PROGRAMS) ## Build the e2e-test binary
29 |
30 | .PHONY: build-image
31 | build-image: ## Build the e2e-test image
32 | docker build -t $(REGISTRY)/e2e_test:$(TAG) .
33 |
34 | .PHONY: publish-image
35 | publish-image:
36 | docker push $(REGISTRY)/e2e_test:$(TAG)
37 |
38 | .PHONY: e2e_test
39 | e2e_test: check-go-version
40 | @CGO_ENABLED=0 go test -c -trimpath -ldflags="-buildid= -w" -o $@ .
41 |
42 | .PHONY: clean
43 | clean: ## Remove build artifacts
44 | $(RM_F) internal/pkg/assets/assets.go
45 | $(RM_F) $(PROGRAMS)
46 |
47 | .PHONY: codegen
48 | codegen: check-go-version ## Generate or update missing Go code defined in feature files
49 | @go run hack/codegen.go -update -dest-path=steps/conformance features/conformance
50 |
51 | .PHONY: verify-codegen
52 | verify-codegen: check-go-version ## Verify if generated Go code is in sync with feature files
53 | @go run hack/codegen.go -dest-path=steps/conformance features
54 |
55 | .PHONY: verify-gherkin
56 | verify-gherkin: check-go-version ## Verify format of gherkin feature files
57 | @hack/verify-gherkin.sh
58 |
59 | .PHONY: help
60 | help: ## Display this help
61 | @echo Targets:
62 | @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9._-]+:.*?## / {printf " %-20s %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
63 |
64 | .PHONY: check-go-version
65 | check-go-version:
66 | @hack/check-go-version.sh
67 |
--------------------------------------------------------------------------------
/test/e2e/README.md:
--------------------------------------------------------------------------------
1 | # BFE ingress controller e2e test
2 |
3 | This test follows K8s project [ingress-controller-conformance](https://github.com/kubernetes-sigs/ingress-controller-conformance), and add more test cases for ingress-bfe special features.
4 |
5 | ## How to run
6 |
7 | To run all e2e test cases, execute following command in ingress-bfe project's top directory:
8 |
9 | ```
10 | $ make e2e-test
11 | ```
12 | It would automatically start the whole testing with following procedures:
13 |
14 | - Build bfe-ingress-controller docker image
15 | - Prepare test environment, including spining up a local k8s cluster with [Kind](https://kind.sigs.k8s.io/), loading docker images, etc. All scripts used to prepare environment are located in [test/script](../script).
16 | - Execute test cases by running [run.sh](./run.sh), which actually build and execute program e2e_test.
17 |
18 | ## Contributing
19 |
20 | We encourage contributors write e2e test case for new feature needed to be merged into ingress-bfe.
21 |
22 | The test code is based on BDD testing framework [godog](https://github.com/cucumber/godog), a testing framework of [cucumber](https://cucumber.io/). It uses [Gherkin Syntax]( https://cucumber.io/docs/gherkin/reference/) to describe test case.
23 |
24 | Steps to add new test case as below:
25 |
26 | ### Step1: Create Gherkin feature
27 |
28 | * Create feature file to describe your test case.
29 |
30 | All feature files are under directory [test/e2e/features](./features). Please put your feature file into proper sub-directory. For example, features//.feature
31 | > Try to reuse steps from existing feature files if possible.
32 |
33 | ### Step2: Create steps definition
34 |
35 | * Generate steps.go for your case. Under directory test/e2e, run:
36 |
37 | ```bash
38 | $ go run hack/codegen.go -dest-path=steps/ features//.feature
39 | ```
40 |
41 |
42 | * Edit generated code, implement all generated functions. If you reuse step description from other feature file, you can also reuse corresponding function from that `step.go` file in this step.
43 |
44 | ### Step3: Add Init function into e2e_test.go
45 |
46 | * In e2e_test.go, add generated feature file and InitializeScenario function into map `features`.
47 |
48 | ```go
49 | var (
50 | features = map[string]InitialFunc{
51 | "features/conformance/host_rules.feature": {hostrules.InitializeScenario, nil},
52 | ...
53 | }
54 | )
55 |
56 | ```
57 |
58 | ### Step4: Build and run
59 |
60 |
61 |
62 | * Build e2e_test:
63 |
64 | ```bash
65 | $ make build
66 | ```
67 |
68 | * Run your case, using `--feature` to specify the feature file.
69 |
70 | ```bash
71 | $ ./e2e_test --feature features//.feature
72 | ```
73 | > Before running, your testing environment must be ready.
74 |
75 | * Run all cases
76 | ```bash
77 | $ ./run.sh
78 | ```
79 |
--------------------------------------------------------------------------------
/test/e2e/features/conformance/default_backend.feature:
--------------------------------------------------------------------------------
1 | @sig-network @conformance @release-1.22
2 | Feature: Default backend
3 | An Ingress with no rules sends all traffic to the single default backend.
4 | The default backend is part of the Ingress resource spec field `defaultBackend`.
5 |
6 | If none of the hosts or paths match the HTTP request in the
7 | Ingress objects, the traffic is routed to your default backend.
8 |
9 | Background:
10 | Given a new random namespace
11 | Given an Ingress resource named "default-backend" with this spec:
12 | """
13 | defaultBackend:
14 | service:
15 | name: echo-service
16 | port:
17 | number: 3000
18 | """
19 | Then The Ingress status shows the IP address or FQDN where it is exposed
20 |
21 | Scenario Outline: An Ingress with no rules should send all requests to the default backend
22 | When I send a "" request to http://""/""
23 | Then the response status-code must be 200
24 | And the response must be served by the "echo-service" service
25 | And the response proto must be "HTTP/1.1"
26 | And the response headers must contain with matching
27 | | key | value |
28 | | Content-Length | * |
29 | | Content-Type | * |
30 | | Date | * |
31 | | Server | * |
32 | And the request method must be ""
33 | And the request path must be ""
34 | And the request proto must be "HTTP/1.1"
35 | And the request headers must contain with matching
36 | | key | value |
37 | | User-Agent | Go-http-client/1.1 |
38 |
39 | Examples:
40 | | method | host | path |
41 | | GET | my-host | |
42 | | GET | my-host | sub-path |
43 | | POST | some-host | |
44 | | PUT | | resource |
45 | | DELETE | some-host | resource |
46 | | PATCH | my-host | resource |
47 |
--------------------------------------------------------------------------------
/test/e2e/features/conformance/host_rules.feature:
--------------------------------------------------------------------------------
1 | @sig-network @conformance @release-1.22
2 | Feature: Host rules
3 | An Ingress may define routing rules based on the request host.
4 |
5 | If the HTTP request host matches one of the hosts in the
6 | Ingress objects, the traffic is routed to its backend service.
7 |
8 | Background:
9 | Given a new random namespace
10 | Given a self-signed TLS secret named "conformance-tls" for the "foo.bar.com" hostname
11 | Given an Ingress resource
12 | """
13 | apiVersion: networking.k8s.io/v1
14 | kind: Ingress
15 | metadata:
16 | name: host-rules
17 | spec:
18 | tls:
19 | - hosts:
20 | - foo.bar.com
21 | secretName: conformance-tls
22 | rules:
23 | - host: "*.foo.com"
24 | http:
25 | paths:
26 | - path: /
27 | pathType: Prefix
28 | backend:
29 | service:
30 | name: wildcard-foo-com
31 | port:
32 | number: 8080
33 |
34 | - host: foo.bar.com
35 | http:
36 | paths:
37 | - path: /
38 | pathType: Prefix
39 | backend:
40 | service:
41 | name: foo-bar-com
42 | port:
43 | number: 80
44 |
45 | """
46 | Then The Ingress status shows the IP address or FQDN where it is exposed
47 |
48 |
49 | Scenario: An Ingress with a host rule should send TLS traffic to the matching backend service
50 | (host foo.bar.com matches request foo.bar.com)
51 |
52 | When I send a "GET" request to "https://foo.bar.com"
53 | Then the secure connection must verify the "foo.bar.com" hostname
54 | And the response status-code must be 200
55 | And the response must be served by the "foo-bar-com" service
56 | And the request host must be "foo.bar.com"
57 |
58 | Scenario: An Ingress with a host rule should send traffic to the matching backend service
59 | (host foo.bar.com matches request foo.bar.com)
60 |
61 | When I send a "GET" request to "http://foo.bar.com"
62 | And the response status-code must be 200
63 | And the response must be served by the "foo-bar-com" service
64 | And the request host must be "foo.bar.com"
65 |
66 | Scenario: An Ingress with a host rule should not route traffic when hostname does not match
67 | (host foo.bar.com does not match request subdomain.bar.com)
68 |
69 | When I send a "GET" request to "http://subdomain.bar.com"
70 | Then the response status-code must be 500
71 |
72 | Scenario: An Ingress with a wildcard host rule should send traffic to the matching backend service
73 | (Matches based on shared suffix)
74 |
75 | When I send a "GET" request to "http://bar.foo.com"
76 | Then the response status-code must be 200
77 | And the response must be served by the "wildcard-foo-com" service
78 | And the request host must be "bar.foo.com"
79 |
80 | Scenario: An Ingress with a wildcard host rule should not route traffic matching on more than a single dns label
81 | (No match, wildcard only covers a single DNS label)
82 |
83 | When I send a "GET" request to "http://baz.bar.foo.com"
84 | Then the response status-code must be 500
85 |
86 | Scenario: An Ingress with a wildcard host rule should not route traffic matching no dns label
87 | (No match, wildcard only covers a single DNS label)
88 |
89 | When I send a "GET" request to "http://foo.com"
90 | Then the response status-code must be 500
91 |
--------------------------------------------------------------------------------
/test/e2e/features/conformance/ingress_class.feature:
--------------------------------------------------------------------------------
1 | @sig-network @conformance @release-1.22
2 | Feature: Ingress class
3 | Ingresses can be implemented by different controllers, often with different configuration.
4 | Each Ingress definition could specify a class, a reference to an IngressClass resource that contains
5 | additional configuration including the name of the controller that should implement the class.
6 |
7 | https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class
8 |
9 | Scenario: An Ingress with an invalid ingress class should not send traffic to the matching backend service
10 | Given an Ingress resource in a new random namespace
11 | """
12 | apiVersion: networking.k8s.io/v1
13 | kind: Ingress
14 | metadata:
15 | name: test-ingress-class
16 | spec:
17 | ingressClassName: some-invalid-class-name
18 | rules:
19 | - host: "ingress-class"
20 | http:
21 | paths:
22 | - path: /
23 | pathType: Prefix
24 | backend:
25 | service:
26 | name: ingress-class-prefix
27 | port:
28 | number: 8080
29 |
30 | """
31 | Then The Ingress status should not contain the IP address or FQDN
32 |
--------------------------------------------------------------------------------
/test/e2e/features/conformance/load_balancing.feature:
--------------------------------------------------------------------------------
1 | @sig-network @conformance @release-1.22
2 | Feature: Load Balancing
3 | An Ingress exposing a backend service with multiple replicas should use all the pods available
4 | The feature sessionAffinity is not configured in the backend service https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#service-v1-core
5 |
6 | Background:
7 | Given an Ingress resource in a new random namespace
8 | """
9 | apiVersion: networking.k8s.io/v1
10 | kind: Ingress
11 | metadata:
12 | name: path-rules
13 | spec:
14 | rules:
15 | - host: "load-balancing"
16 | http:
17 | paths:
18 | - path: /
19 | pathType: Prefix
20 | backend:
21 | service:
22 | name: echo-service
23 | port:
24 | number: 8080
25 |
26 | """
27 | Then The Ingress status shows the IP address or FQDN where it is exposed
28 | Then The backend deployment "echo-service" for the ingress resource is scaled to 10
29 |
30 | Scenario Outline: An Ingress should send all requests to the backend
31 | When I send 100 requests to "http://load-balancing"
32 | Then all the responses status-code must be 200 and the response body should contain the IP address of 10 different Kubernetes pods
33 |
--------------------------------------------------------------------------------
/test/e2e/features/rules/path_err.feature:
--------------------------------------------------------------------------------
1 | @ingress.rule @release-1.22
2 | Feature: Path error rules
3 | An Ingress status error when given error ingress.
4 |
5 | Scenario: An Ingress with path rules a status should be error and not send traffic to the matching backend service
6 | (path rule a)
7 | Given an Ingress resource in a new random namespace should not create
8 | """
9 | apiVersion: networking.k8s.io/v1
10 | kind: Ingress
11 | metadata:
12 | name: path-err-rules
13 | spec:
14 | rules:
15 | - host: "exact-path-rules-cookie-uid"
16 | http:
17 | paths:
18 | - path: a
19 | pathType: Exact
20 | backend:
21 | service:
22 | name: foo-exact
23 | port:
24 | number: 3000
25 | """
26 |
27 | Scenario: An Ingress with path rules null status should be error and not send traffic to the matching backend service
28 | (path rule null)
29 | Given an Ingress resource in a new random namespace should not create
30 | """
31 | apiVersion: networking.k8s.io/v1
32 | kind: Ingress
33 | metadata:
34 | name: path-err-rules
35 | spec:
36 | rules:
37 | - host: "exact-path-rules-cookie-uid"
38 | http:
39 | paths:
40 | - path:
41 | pathType: Exact
42 | backend:
43 | service:
44 | name: foo-exact
45 | port:
46 | number: 3000
47 | """
48 |
--------------------------------------------------------------------------------
/test/e2e/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/bfenetworks/ingress-bfe/test/e2e
2 |
3 | go 1.16
4 |
5 | require (
6 | github.com/cucumber/gherkin-go/v11 v11.0.0
7 | github.com/cucumber/godog v0.12.3
8 | github.com/cucumber/messages-go/v10 v10.0.3
9 | github.com/cucumber/messages-go/v16 v16.0.1 // indirect
10 | github.com/iancoleman/orderedmap v0.1.0
11 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4
12 | k8s.io/api v0.19.2
13 | k8s.io/apimachinery v0.19.2
14 | k8s.io/client-go v0.19.2
15 | k8s.io/klog/v2 v2.3.0
16 | sigs.k8s.io/yaml v1.2.0
17 | )
18 |
--------------------------------------------------------------------------------
/test/e2e/hack/boilerplate/boilerplate.go.txt:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright YEAR The Kubernetes Authors.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
--------------------------------------------------------------------------------
/test/e2e/hack/boilerplate/boilerplate.py.txt:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Copyright YEAR The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 |
--------------------------------------------------------------------------------
/test/e2e/hack/boilerplate/boilerplate.sh.txt:
--------------------------------------------------------------------------------
1 | # Copyright YEAR The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 |
--------------------------------------------------------------------------------
/test/e2e/hack/check-go-version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2020 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | if [ -n "$DEBUG" ]; then
18 | set -x
19 | fi
20 |
21 | set -o errexit
22 | set -o nounset
23 | set -o pipefail
24 |
25 | MINIMUM_GO_VERSION=go1.15
26 |
27 | if [[ -z "$(command -v go)" ]]; then
28 | echo "
29 | Can't find 'go' in PATH, please fix and retry.
30 | See http://golang.org/doc/install for installation instructions.
31 | "
32 | exit 1
33 | fi
34 |
35 | IFS=" " read -ra go_version <<< "$(go version)"
36 |
37 | if [[ "${MINIMUM_GO_VERSION}" != $(echo -e "${MINIMUM_GO_VERSION}\n${go_version[2]}" | sort -s -t. -k 1,1 -k 2,2n -k 3,3n | head -n1) && "${go_version[2]}" != "devel" ]]; then
38 | echo "
39 | Detected go version: ${go_version[*]}.
40 | ingress-nginx requires ${MINIMUM_GO_VERSION} or greater.
41 |
42 | Please install ${MINIMUM_GO_VERSION} or later.
43 | "
44 | exit 1
45 | fi
46 |
--------------------------------------------------------------------------------
/test/e2e/hack/codegen.tmpl:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2021 The BFE Authors.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package {{ .Package }}
18 |
19 | import (
20 | "github.com/cucumber/godog"
21 | "github.com/cucumber/messages-go/v16"
22 |
23 | "github.com/bfenetworks/ingress-bfe/test/e2e/pkg/kubernetes"
24 | tstate "github.com/bfenetworks/ingress-bfe/test/e2e/pkg/state"
25 | )
26 |
27 | var (
28 | state *tstate.Scenario
29 | )
30 |
31 | // IMPORTANT: Steps definitions are generated and should not be modified
32 | // by hand but rather through make codegen. DO NOT EDIT.
33 |
34 | // InitializeScenario configures the Feature to test
35 | func InitializeScenario(ctx *godog.ScenarioContext) { {{- range .NewFunctions }}
36 | ctx.Step({{ backticked .Expr | unescape }}, {{ .Name }}){{end}}
37 |
38 | ctx.BeforeScenario(func(*godog.Scenario) {
39 | state = tstate.New()
40 | })
41 |
42 | ctx.AfterScenario(func(*messages.Pickle, error) {
43 | // delete namespace an all the content
44 | _ = kubernetes.DeleteNamespace(kubernetes.KubeClient, state.Namespace)
45 | })
46 | }
47 | {{ range .NewFunctions }}
48 | func {{ .Name }}{{ argsFromMap .Args false }} error {
49 | return godog.ErrPending
50 | }
51 | {{ end }}
52 |
--------------------------------------------------------------------------------
/test/e2e/hack/kube-env.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2014 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Some useful colors.
18 | if [[ -z "${color_start-}" ]]; then
19 | declare -r color_start="\033["
20 | declare -r color_red="${color_start}0;31m"
21 | declare -r color_yellow="${color_start}0;33m"
22 | declare -r color_green="${color_start}0;32m"
23 | declare -r color_norm="${color_start}0m"
24 | fi
25 |
26 | # Returns the server version as MMmmpp, with MM as the major
27 | # component, mm the minor component, and pp as the patch
28 | # revision. e.g. 0.7.1 is echoed as 701, and 1.0.11 would be
29 | # 10011. (This makes for easy integer comparison in bash.)
30 | function kube_server_version() {
31 | local server_version
32 | local major
33 | local minor
34 | local patch
35 |
36 | # This sed expression is the POSIX BRE to match strings like:
37 | # Server Version: &version.Info{Major:"0", Minor:"7+", GitVersion:"v0.7.0-dirty", GitCommit:"ad44234f7152e9c66bc2853575445c7071335e57", GitTreeState:"dirty"}
38 | # and capture the GitVersion portion (which has the patch level)
39 | server_version=$(${KUBECTL} --match-server-version=false version | grep "Server Version:")
40 | read major minor patch < <(
41 | echo ${server_version} | \
42 | sed "s/.*GitVersion:\"v\([0-9]\{1,\}\)\.\([0-9]\{1,\}\)\.\([0-9]\{1,\}\).*/\1 \2 \3/")
43 | printf "%02d%02d%02d" ${major} ${minor} ${patch} | sed 's/^0*//'
44 | }
45 |
--------------------------------------------------------------------------------
/test/e2e/hack/verify-all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2014 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -o errexit
18 | set -o nounset
19 | set -o pipefail
20 |
21 | KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
22 | source "${KUBE_ROOT}/hack/kube-env.sh"
23 |
24 | SILENT=true
25 |
26 | function is-excluded {
27 | for e in $EXCLUDE; do
28 | if [[ $1 -ef ${BASH_SOURCE} ]]; then
29 | return
30 | fi
31 | if [[ $1 -ef "$KUBE_ROOT/hack/$e" ]]; then
32 | return
33 | fi
34 | done
35 | return 1
36 | }
37 |
38 | while getopts ":v" opt; do
39 | case $opt in
40 | v)
41 | SILENT=false
42 | ;;
43 | \?)
44 | echo "Invalid flag: -$OPTARG" >&2
45 | exit 1
46 | ;;
47 | esac
48 | done
49 |
50 | if $SILENT ; then
51 | echo "Running in the silent mode, run with -v if you want to see script logs."
52 | fi
53 |
54 | EXCLUDE="verify-all.sh verify-codegen.sh"
55 |
56 | ret=0
57 | for t in `ls $KUBE_ROOT/hack/verify-*.sh`
58 | do
59 | if is-excluded $t ; then
60 | echo "Skipping $t"
61 | continue
62 | fi
63 | if $SILENT ; then
64 | echo -e "Verifying $t"
65 | if bash "$t" &> /dev/null; then
66 | echo -e "${color_green}SUCCESS${color_norm}"
67 | else
68 | echo -e "${color_red}FAILED${color_norm}"
69 | ret=1
70 | fi
71 | else
72 | bash "$t" || ret=1
73 | fi
74 | done
75 |
76 | exit $ret
77 |
78 | # ex: ts=2 sw=2 et filetype=sh
79 |
--------------------------------------------------------------------------------
/test/e2e/hack/verify-boilerplate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2014 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -o errexit
18 | set -o nounset
19 | set -o pipefail
20 |
21 | KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
22 |
23 | boilerDir="${KUBE_ROOT}/hack/boilerplate"
24 | boiler="${boilerDir}/boilerplate.py"
25 |
26 | files_need_boilerplate=($(${boiler} "$@"))
27 |
28 | # Run boilerplate check
29 | if [[ ${#files_need_boilerplate[@]} -gt 0 ]]; then
30 | for file in "${files_need_boilerplate[@]}"; do
31 | echo "Boilerplate header is wrong for: ${file}"
32 | done
33 |
34 | exit 1
35 | fi
36 |
--------------------------------------------------------------------------------
/test/e2e/hack/verify-gherkin.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2014 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # GoFmt apparently is changing @ head...
18 |
19 | set -o errexit
20 | set -o nounset
21 | set -o pipefail
22 |
23 | KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
24 |
25 | if ! command -v reformat-gherkin --version &> /dev/null; then
26 | echo "Please install reformat-gherkin running \"pip install reformat-gherkin\""
27 | exit 1
28 | fi
29 |
30 | reformat-gherkin --check ${KUBE_ROOT}/features
31 |
--------------------------------------------------------------------------------
/test/e2e/hack/verify-gofmt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2014 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # GoFmt apparently is changing @ head...
18 |
19 | set -o errexit
20 | set -o nounset
21 | set -o pipefail
22 |
23 | KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
24 |
25 | cd "${KUBE_ROOT}"
26 |
27 | find_files() {
28 | find . -not \( \
29 | \( \
30 | -wholename './.git' \
31 | -o -wholename '*/vendor/*' \
32 | -o -wholename '*bindata.go' \
33 | \) -prune \
34 | \) -name '*.go'
35 | }
36 |
37 | GOFMT="gofmt -s"
38 | bad_files=$(find_files | xargs $GOFMT -l)
39 | if [[ -n "${bad_files}" ]]; then
40 | echo "!!! '$GOFMT' needs to be run on the following files: "
41 | echo "${bad_files}"
42 | exit 1
43 | fi
44 |
--------------------------------------------------------------------------------
/test/e2e/hack/verify-golint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2014 The Kubernetes Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -o errexit
18 | set -o nounset
19 | set -o pipefail
20 |
21 | KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
22 |
23 | if ! command -v golint &> /dev/null; then
24 | go get golang.org/x/lint/golint
25 | fi
26 |
27 | cd "${KUBE_ROOT}"
28 |
29 | PACKAGES=($(go list ./test/...))
30 | bad_files=()
31 | for package in "${PACKAGES[@]}"; do
32 | out=$(golint -min_confidence=0.9 "${package}" | grep -v -E '(should not use dot imports)' || :)
33 | if [[ -n "${out}" ]]; then
34 | bad_files+=("${out}")
35 | fi
36 | done
37 | if [[ "${#bad_files[@]}" -ne 0 ]]; then
38 | echo "!!! golint problems: "
39 | echo "${bad_files[@]}"
40 | exit 1
41 | fi
42 |
43 | # ex: ts=2 sw=2 et filetype=sh
44 |
--------------------------------------------------------------------------------
/test/e2e/images/echoserver/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2019 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Build
16 | FROM golang:1.16-alpine3.14 as builder
17 |
18 | ENV CGO_ENABLED=0
19 |
20 | WORKDIR /echoserver/
21 |
22 | COPY echoserver.go .
23 |
24 | RUN GO111MODULE=off go build -trimpath -ldflags="-buildid= -s -w" -o echoserver .
25 |
26 | # Use distroless as minimal base image to package the binary
27 | # Refer to https://github.com/GoogleContainerTools/distroless for more details
28 | FROM alpine:3.14
29 | WORKDIR /
30 | COPY --from=builder /echoserver /
31 |
32 | ENTRYPOINT ["/echoserver"]
33 |
--------------------------------------------------------------------------------
/test/e2e/images/echoserver/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | TAG ?= 0.0.1
16 |
17 | REGISTRY ?= local
18 | IMAGE = echoserver
19 |
20 | .PHONY: build-image
21 | build-image: ## Build the ingress conformance image
22 | docker build -t $(REGISTRY)/$(IMAGE):$(TAG) .
23 |
24 | .PHONY: publish-image
25 | publish-image:
26 | docker push $(REGISTRY)/$(IMAGE):$(TAG)
27 |
--------------------------------------------------------------------------------
/test/e2e/images/echoserver/echoserver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bfenetworks/ingress-bfe/593a473ce6016f41d99de24722008423e5085322/test/e2e/images/echoserver/echoserver
--------------------------------------------------------------------------------
/test/e2e/images/reports/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # build stage
16 | FROM node:lts-alpine
17 |
18 | WORKDIR /app
19 |
20 | COPY src /app
21 |
22 | RUN npm install --production
23 |
24 | CMD ["node", "/app/index.js"]
25 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright 2020 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | TAG ?= 0.0.1
16 |
17 | REGISTRY ?= local
18 | IMAGE = reports-builder
19 |
20 | .PHONY: build-image
21 | build-image: ## Build the e2e test report image
22 | docker build -t $(REGISTRY)/$(IMAGE):$(TAG) .
23 |
24 | .PHONY: publish-image
25 | publish-image:
26 | docker push $(REGISTRY)/$(IMAGE):$(TAG)
27 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/README.md:
--------------------------------------------------------------------------------
1 | # Report builder for conformance tests
2 |
3 | ### Environment variables:
4 |
5 | #### Mandatory
6 |
7 | | Variable | Description |
8 | | ------------- | ------------- |
9 | | INPUT_DIRECTORY | Directory that contains the cucumber json files |
10 | | OUTPUT_DIRECTORY | Directory where the reports will be generated |
11 |
12 | #### Optional
13 |
14 | | Variable | Description |
15 | | ------------- | ------------- |
16 | | INGRESS_CONTROLLER | Information about the ingress controller |
17 | | CONTROLLER_VERSION | ingress controller version |
18 |
19 | ## Building
20 |
21 | ```console
22 | make
23 | ```
24 |
25 | ### Generation of reports
26 |
27 | ```console
28 | docker run \
29 | -e BUILD=$(git rev-parse --short HEAD) \
30 | -e INPUT_DIRECTORY=/input \
31 | -e OUTPUT_DIRECTORY=/output \
32 | -v $PWD:/input:ro \
33 | -v $PWD/output:/output \
34 | local/reports-builder:0.0
35 | ```
36 |
37 | ### Display
38 |
39 | The reports are plain HTML files. The file located in `OUTPUT_DIRECTORY/index.html` renders the initial page.
40 |
41 | Using any web server capable of render html is enough.
42 | Like:
43 |
44 | ```console
45 | cd $OUTPUT_DIRECTORY
46 |
47 | python -m http.server 8000
48 | Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
49 |
50 | ```
51 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/.gitignore:
--------------------------------------------------------------------------------
1 | output
2 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | env:
2 | browser: true
3 | commonjs: true
4 | es2020: true
5 | extends:
6 | - airbnb-base
7 | parserOptions:
8 | ecmaVersion: 11
9 | rules: {}
10 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Wim Selles
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/README.MD:
--------------------------------------------------------------------------------
1 | Cucumber HTML Reporter
2 | ===============================
3 |
4 | Based on [multiple-cucumber-html-reporter](github/wswebcreation/multiple-cucumber-html-reporter)
5 |
6 | ## Credits
7 |
8 | In the search for a reporting tools for Cucumber I found a few tools that helped me a lot:
9 |
10 | - [multiple-cucumber-html-reporter](github/wswebcreation/multiple-cucumber-html-reporter)
11 | - [cucumber-html-repository](https://github.com/gkushang/cucumber-html-reporter)
12 | - [cucumber-html-report](https://github.com/leinonen/cucumber-html-report)
13 | - [cucumber-protractor-report](https://github.com/JesterXL/cucumber-protractor-report)
14 | - [grunt-protractor-cucumber-html-report](https://github.com/robhil/grunt-protractor-cucumber-html-report)
15 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/lib/collect-jsons.js:
--------------------------------------------------------------------------------
1 | const { readFileSync, statSync } = require('fs-extra');
2 | const { findJsonFiles, formatToLocalIso } = require('./utils');
3 | const { parseFeatureHooks, parseMetadata } = require('./parse.cucumber.data');
4 |
5 | module.exports = function collectJSONS(options) {
6 | const jsonOutput = [];
7 | const files = findJsonFiles(options.jsonDir);
8 |
9 | if (files.length === 0) {
10 | console.log(`WARNING: No JSON files found in '${options.jsonDir}'. NO REPORT CAN BE CREATED!`);
11 | return [];
12 | }
13 |
14 | files.map((file) => {
15 | let data;
16 | // Cucumber json can be empty, it's likely being created by another process (#47)
17 | // or the data could not be a valid JSON-file
18 | try {
19 | data = JSON.parse(readFileSync(file).toString());
20 | } catch (e) {
21 | data = [];
22 | console.log(`WARNING: File: '${file}' had no valid JSON data due to error:'${e}'. CONTENT WAS NOT LOADED!`);
23 | }
24 |
25 | const jsonData = Array.isArray(data) ? data : [data];
26 | const stats = statSync(file);
27 | const reportTime = formatToLocalIso(stats.birthtime);
28 |
29 | jsonData.map((json) => {
30 | json = parseMetadata(json, options.metadata);
31 |
32 | if (options.displayReportTime) {
33 | json.metadata = {
34 | ...json.metadata,
35 | ...{ reportTime },
36 | };
37 | }
38 |
39 | // Only check the feature hooks if there are elements (fail safe)
40 | const { elements } = json;
41 |
42 | if (elements) {
43 | json.elements = elements.map((scenario) => {
44 | const { before, after } = scenario;
45 |
46 | if (before) {
47 | scenario.steps = parseFeatureHooks(before, 'Before')
48 | .concat(scenario.steps);
49 | }
50 | if (after) {
51 | scenario.steps = scenario.steps
52 | .concat(parseFeatureHooks(after, 'After'));
53 | }
54 |
55 | return scenario;
56 | });
57 | }
58 |
59 | jsonOutput.push(json);
60 | });
61 | });
62 |
63 | return jsonOutput;
64 | };
65 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multiple-cucumber-html-reporter",
3 | "version": "1.18.0",
4 | "description": "Generate beautiful Cucumber reports for multiple instances purposes",
5 | "keywords": [
6 | "cucumber",
7 | "html",
8 | "test report",
9 | "multiple-cucumber-html-reporter",
10 | "html report",
11 | "json to html"
12 | ],
13 | "main": "lib/generate-report.js",
14 | "license": "MIT",
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/wswebcreation/multiple-cucumber-html-reporter.git"
18 | },
19 | "author": "wswebcreation",
20 | "homepage": "https://github.com/wswebcreation/multiple-cucumber-html-reporter#readme",
21 | "dependencies": {
22 | "ejs": "^3.1.3",
23 | "fs-extra": "^9.0.1",
24 | "js-base64": "^3.4.1",
25 | "moment": "^2.27.0"
26 | },
27 | "devDependencies": {
28 | "coveralls": "^3.1.0",
29 | "eslint": "^7.7.0",
30 | "eslint-config-airbnb-base": "^14.2.0",
31 | "eslint-plugin-import": "^2.22.0",
32 | "jest": "^26.2.1",
33 | "np": "^6.3.2"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/templates/components/features-overview.chart.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Features
7 |
8 |
9 |
10 | Status |
11 | Progress |
12 |
13 |
14 |
15 |
16 |
17 | Passed
18 | |
19 | <%- suite.totalFeaturesCount.passed.percentage %>% |
20 |
21 |
22 |
23 | Failed
24 | |
25 | <%- suite.totalFeaturesCount.failed.percentage %>% |
26 |
27 | <%if(suite.totalFeaturesCount.ambiguous.count > 0){ %>
28 |
29 |
30 | Ambiguous
31 | |
32 | <%- suite.totalFeaturesCount.ambiguous.percentage %>% |
33 |
34 | <%} %>
35 | <%if(suite.totalFeaturesCount.notDefined.count > 0){ %>
36 |
37 |
38 | Not Defined
39 | |
40 | <%- suite.totalFeaturesCount.notDefined.percentage %>% |
41 |
42 | <%} %>
43 | <%if(suite.totalFeaturesCount.pending.count > 0){ %>
44 |
45 |
46 | Pending
47 | |
48 | <%- suite.totalFeaturesCount.pending.percentage %>% |
49 |
50 | <%} %>
51 | <%if(suite.totalFeaturesCount.skipped.count > 0){ %>
52 |
53 |
54 | Skipped
55 | |
56 | <%- suite.totalFeaturesCount.skipped.percentage %>% |
57 |
58 | <%} %>
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/templates/components/scenarios-overview.chart.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Scenarios
7 |
8 |
9 |
10 | Status |
11 | Progress |
12 |
13 |
14 |
15 |
16 |
17 | Passed
18 | |
19 | <%- scenarios.passed.percentage %>% |
20 |
21 |
22 |
23 | Failed
24 | |
25 | <%- scenarios.failed.percentage %>% | <%if (scenarios.ambiguous.count > 0) { %>
26 |
27 |
28 |
29 | Ambiguous
30 | |
31 | <%- scenarios.ambiguous.percentage %>% |
32 |
<%} %><%if (scenarios.notDefined.count > 0) { %>
33 |
34 |
35 | Not defined
36 | |
37 | <%- scenarios.notDefined.percentage %>% |
38 |
<%} %><%if (scenarios.pending.count > 0) { %>
39 |
40 |
41 | Pending
42 | |
43 | <%- scenarios.pending.percentage %>% |
44 |
<%} %><%if (scenarios.skipped.count > 0) { %>
45 |
46 |
47 | Skipped
48 | |
49 | <%- scenarios.skipped.percentage %>% |
50 |
<%} %>
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/cucumber-html-reporter/templates/generic.js:
--------------------------------------------------------------------------------
1 | $('body').tooltip({
2 | selector: '[data-toggle="tooltip"]'
3 | });
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/index.js:
--------------------------------------------------------------------------------
1 | const report = require("./cucumber-html-reporter");
2 | const assert = require("assert");
3 |
4 | assert(process.env.INPUT_DIRECTORY, "Environment variable INPUT_DIRECTORY is not optional");
5 | assert(process.env.OUTPUT_DIRECTORY, "Environment variable OUTPUT_DIRECTORY is not optional");
6 |
7 | report.generate({
8 | jsonDir: process.env.INPUT_DIRECTORY,
9 | reportPath: process.env.OUTPUT_DIRECTORY,
10 | pageFooter: 'BFE ingress controller e2e test
',
11 | ingress: {
12 | controller: process.env.INGRESS_CONTROLLER || 'N/A',
13 | version: process.env.CONTROLLER_VERSION || 'N/A'
14 | },
15 | buildTime: process.env.BUILD
16 | });
17 |
--------------------------------------------------------------------------------
/test/e2e/images/reports/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ingress-conformance-reports",
3 | "version": "0.0.1",
4 | "dependencies": {
5 | "ejs": "^3.1.5",
6 | "fs-extra": "^9.0.1",
7 | "js-base64": "^3.4.5",
8 | "moment": "^2.27.0"
9 | },
10 | "scripts": {
11 | "run": "node index"
12 | },
13 | "license": "Apache-2.0"
14 | }
15 |
--------------------------------------------------------------------------------
/test/e2e/pkg/files/files.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2020 The Kubernetes Authors.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package files
18 |
19 | import (
20 | "fmt"
21 | "io/ioutil"
22 | "os"
23 | )
24 |
25 | // Read tries to retrieve the desired file content from
26 | // one of the registered file sources.
27 | func Read(path string) ([]byte, error) {
28 | if exists := Exists(path); !exists {
29 | return nil, fmt.Errorf("file %v does not exists", path)
30 | }
31 |
32 | data, err := ioutil.ReadFile(path)
33 | if err != nil {
34 | return nil, fmt.Errorf("fatal error retrieving test file %s: %s", path, err)
35 | }
36 |
37 | return data, nil
38 | }
39 |
40 | // Exists checks whether a file could be read. Unexpected errors
41 | // are handled by calling the fail function, which then should
42 | // abort the current test.
43 | func Exists(path string) bool {
44 | _, err := os.Stat(path)
45 | if os.IsNotExist(err) {
46 | return false
47 | }
48 |
49 | return true
50 | }
51 |
52 | // IsDir reports whether path is a directory
53 | func IsDir(path string) bool {
54 | info, err := os.Stat(path)
55 | if os.IsNotExist(err) {
56 | return false
57 | }
58 |
59 | return info.IsDir()
60 | }
61 |
--------------------------------------------------------------------------------
/test/e2e/pkg/kubernetes/templates/templates.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2020 The Kubernetes Authors.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package templates
18 |
19 | import (
20 | "bytes"
21 | "fmt"
22 | text_template "text/template"
23 | )
24 |
25 | var k8sTemplates = map[string]string{
26 | "deployment": `
27 | apiVersion: apps/v1
28 | kind: Deployment
29 | metadata:
30 | name: {{ .Name }}
31 | spec:
32 | replicas: 1
33 | strategy:
34 | type: RollingUpdate
35 | selector:
36 | matchLabels:
37 | app: {{ .MatchLabels }}
38 | template:
39 | metadata:
40 | labels:
41 | app: {{ .Labels }}
42 | spec:
43 | containers:
44 | - name: ingress-conformance-echo
45 | image: {{ .Image }}
46 | env:
47 | - name: POD_NAME
48 | valueFrom:
49 | fieldRef:
50 | fieldPath: metadata.name
51 | - name: NAMESPACE
52 | valueFrom:
53 | fieldRef:
54 | fieldPath: metadata.namespace
55 | - name: INGRESS_NAME
56 | value: {{ .Ingress }}
57 | - name: SERVICE_NAME
58 | value: {{ .Service }}
59 | ports:
60 | - name: {{ .PortName }}
61 | containerPort: 3000
62 | livenessProbe:
63 | httpGet:
64 | path: /health
65 | port: 3000
66 | scheme: HTTP
67 | initialDelaySeconds: 1
68 | periodSeconds: 1
69 | timeoutSeconds: 1
70 | successThreshold: 1
71 | failureThreshold: 10
72 | readinessProbe:
73 | httpGet:
74 | path: /health
75 | port: 3000
76 | scheme: HTTP
77 | initialDelaySeconds: 1
78 | periodSeconds: 1
79 | timeoutSeconds: 1
80 | successThreshold: 1
81 | failureThreshold: 10
82 | `,
83 | "service": `
84 | apiVersion: v1
85 | kind: Service
86 | metadata:
87 | name: {{ .Name }}
88 | spec:
89 | type: NodePort
90 | selector:
91 | app: {{ .Selector }}
92 | ports:
93 | - port: {{ .Port }}
94 | targetPort: 3000
95 | `,
96 | }
97 |
98 | var templates = map[string]*text_template.Template{}
99 |
100 | // Load parses templates required to deploy Kubernetes objects
101 | func Load() error {
102 | for name, template := range k8sTemplates {
103 | tmpl, err := text_template.New(name).Parse(template)
104 | if err != nil {
105 | return err
106 | }
107 |
108 | templates[name] = tmpl
109 | }
110 |
111 | return nil
112 | }
113 |
114 | // Render executes a parsed template to the specified data object
115 | func Render(name string, data interface{}) (string, error) {
116 | tmpl, ok := templates[name]
117 | if !ok {
118 | return "", fmt.Errorf("there is no template with name %v", name)
119 | }
120 |
121 | var tpl bytes.Buffer
122 | err := tmpl.Execute(&tpl, data)
123 | if err != nil {
124 | return "", err
125 | }
126 |
127 | return tpl.String(), nil
128 | }
129 |
--------------------------------------------------------------------------------
/test/e2e/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 The BFE Authors.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -ex
18 |
19 | trap TERM
20 |
21 | cd "$(dirname "$0")"
22 |
23 | RESULTS_DIR="${RESULTS_DIR:-$PWD/result}"
24 | if [[ -d $RESULTS_DIR ]]; then
25 | rm -rf $RESULTS_DIR/*
26 | else
27 | mkdir $RESULTS_DIR
28 | fi
29 |
30 | make build
31 |
32 | CUCUMBER_OUTPUT_FORMAT="${CUCUMBER_OUTPUT_FORMAT:-pretty}"
33 | WAIT_FOR_STATUS_TIMEOUT="${WAIT_FOR_STATUS_TIMEOUT:-5m}"
34 | TEST_TIMEOUT="${TEST_TIMEOUT:-0}"
35 | TEST_PARALLEL="${TEST_PARALLEL:-5}"
36 |
37 | ./e2e_test \
38 | --output-directory="${RESULTS_DIR}" \
39 | --feature="${CUCUMBER_FEATURE}" \
40 | --format="${CUCUMBER_OUTPUT_FORMAT}" \
41 | --wait-time-for-ingress-status="${WAIT_FOR_STATUS_TIMEOUT}" \
42 | --wait-time-for-ready="${WAIT_FOR_STATUS_TIMEOUT}" \
43 | --test.timeout="${TEST_TIMEOUT}" \
44 | --feature-parallel="${TEST_PARALLEL}"
45 | ret=$?
46 |
47 | exit 0
48 |
--------------------------------------------------------------------------------
/test/e2e/steps/conformance/ingressclass/steps.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2021 The BFE Authors.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package ingressclass
18 |
19 | import (
20 | "fmt"
21 |
22 | "github.com/cucumber/godog"
23 | "github.com/cucumber/messages-go/v16"
24 |
25 | "github.com/bfenetworks/ingress-bfe/test/e2e/pkg/kubernetes"
26 | tstate "github.com/bfenetworks/ingress-bfe/test/e2e/pkg/state"
27 | )
28 |
29 | var (
30 | state *tstate.Scenario
31 | )
32 |
33 | // IMPORTANT: Steps definitions are generated and should not be modified
34 | // by hand but rather through make codegen. DO NOT EDIT.
35 |
36 | // InitializeScenario configures the Feature to test
37 | func InitializeScenario(ctx *godog.ScenarioContext) {
38 | ctx.Step(`^an Ingress resource in a new random namespace$`, anIngressResourceInANewRandomNamespace)
39 | ctx.Step(`^The Ingress status should not contain the IP address or FQDN$`, theIngressStatusShouldNotContainTheIPAddressOrFQDN)
40 |
41 | ctx.BeforeScenario(func(*godog.Scenario) {
42 | state = tstate.New()
43 | })
44 |
45 | ctx.AfterScenario(func(*messages.Pickle, error) {
46 | // delete namespace an all the content
47 | _ = kubernetes.DeleteNamespace(kubernetes.KubeClient, state.Namespace)
48 | })
49 | }
50 |
51 | func anIngressResourceInANewRandomNamespace(spec *godog.DocString) error {
52 | ns, err := kubernetes.NewNamespace(kubernetes.KubeClient)
53 | if err != nil {
54 | return err
55 | }
56 |
57 | state.Namespace = ns
58 |
59 | ingress, err := kubernetes.IngressFromManifest(state.Namespace, spec.Content)
60 | if err != nil {
61 | return err
62 | }
63 |
64 | err = kubernetes.DeploymentsFromIngress(kubernetes.KubeClient, ingress)
65 | if err != nil {
66 | return err
67 | }
68 |
69 | err = kubernetes.NewIngress(kubernetes.KubeClient, state.Namespace, ingress)
70 | if err != nil {
71 | return err
72 | }
73 |
74 | state.IngressName = ingress.GetName()
75 |
76 | return nil
77 | }
78 |
79 | func theIngressStatusShouldNotContainTheIPAddressOrFQDN() error {
80 | _, err := kubernetes.WaitForIngressAddress(kubernetes.KubeClient, state.Namespace, state.IngressName)
81 | if err == nil {
82 | return fmt.Errorf("waiting for Ingress status should not return an IP address or FQDN")
83 | }
84 |
85 | return nil
86 | }
87 |
--------------------------------------------------------------------------------
/test/e2e/steps/rules/patherr/steps.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2020 The BFE Authors.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package patherr
18 |
19 | import (
20 | "fmt"
21 |
22 | "github.com/cucumber/godog"
23 | "github.com/cucumber/messages-go/v16"
24 |
25 | "github.com/bfenetworks/ingress-bfe/test/e2e/pkg/kubernetes"
26 | tstate "github.com/bfenetworks/ingress-bfe/test/e2e/pkg/state"
27 | )
28 |
29 | var (
30 | state *tstate.Scenario
31 | )
32 |
33 | // IMPORTANT: Steps definitions are generated and should not be modified
34 | // by hand but rather through make codegen. DO NOT EDIT.
35 |
36 | // InitializeScenario configures the Feature to test
37 | func InitializeScenario(ctx *godog.ScenarioContext) {
38 | ctx.Step(`^an Ingress resource in a new random namespace should not create$`, anIngressResourceInANewRandomNamespaceShouldNotCreate)
39 |
40 | ctx.BeforeScenario(func(*godog.Scenario) {
41 | state = tstate.New()
42 | })
43 |
44 | ctx.AfterScenario(func(*messages.Pickle, error) {
45 | // delete namespace an all the content
46 | _ = kubernetes.DeleteNamespace(kubernetes.KubeClient, state.Namespace)
47 | })
48 | }
49 |
50 | func anIngressResourceInANewRandomNamespaceShouldNotCreate(spec *godog.DocString) error {
51 | ns, err := kubernetes.NewNamespace(kubernetes.KubeClient)
52 | if err != nil {
53 | return err
54 | }
55 |
56 | state.Namespace = ns
57 |
58 | ingress, err := kubernetes.IngressFromManifest(state.Namespace, spec.Content)
59 | if err != nil {
60 | return err
61 | }
62 |
63 | err = kubernetes.DeploymentsFromIngress(kubernetes.KubeClient, ingress)
64 | if err != nil {
65 | return err
66 | }
67 |
68 | err = kubernetes.NewIngress(kubernetes.KubeClient, state.Namespace, ingress)
69 | if err == nil {
70 | return fmt.Errorf("create ingress should return error")
71 | }
72 |
73 | state.IngressName = ingress.GetName()
74 |
75 | return nil
76 | }
77 |
--------------------------------------------------------------------------------
/test/script/controller-svc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: bfe-controller-service
5 | namespace: ingress-bfe
6 | labels:
7 | app.kubernetes.io/name: bfe-ingress-controller
8 | app.kubernetes.io/instance: bfe-ingress-controller
9 | spec:
10 | type: NodePort
11 | selector:
12 | app.kubernetes.io/name: bfe-ingress-controller
13 | app.kubernetes.io/instance: bfe-ingress-controller
14 | ports:
15 | - name: http
16 | port: 8080
17 | targetPort: 8080
18 | nodePort: 30000
19 | - name: https
20 | port: 8443
21 | targetPort: 8443
22 | nodePort: 30001
23 |
--------------------------------------------------------------------------------
/test/script/deploy-controller.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright 2022 The BFE Authors
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | set -e
16 |
17 | download_kubectl(){
18 | if [[ "$OSTYPE" == "linux-gnu"* ]]; then
19 | # linux
20 | echo "linux"
21 | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
22 |
23 | elif [[ "$OSTYPE" == "darwin"* ]]; then
24 | # Mac
25 | if [[ $(arch) == 'arm64' ]]; then
26 | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
27 |
28 | else
29 | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
30 | fi
31 | else
32 | echo "unsupported os type: " "$OSTYPE"
33 | exit 1
34 | fi
35 |
36 | chmod +x ./kubectl
37 |
38 | }
39 |
40 | cd "$(dirname "$0")"
41 | VERSION=$1
42 |
43 | IMAGE="bfenetworks/bfe-ingress-controller:"$VERSION
44 |
45 | if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" ]]; then
46 | echo "image does not exist:" "$IMAGE"
47 | exit 1
48 | fi
49 |
50 | if [[ ! -f kubectl ]]; then
51 | download_kubectl
52 | fi
53 |
54 | # update yaml to version
55 | sed "s#image: .*\$#image: $IMAGE#g" ../../examples/controller-all.yaml > controller-all.yaml
56 |
57 | ./kubectl apply -f controller-all.yaml
58 | ./kubectl apply -f controller-svc.yaml -f ingressclass.yaml
59 |
60 |
--------------------------------------------------------------------------------
/test/script/ingressclass.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: networking.k8s.io/v1
2 | kind: IngressClass
3 | metadata:
4 | labels:
5 | app.kubernetes.io/component: controller
6 | name: bfe
7 | namespace: ingress-bfe
8 | annotations:
9 | ingressclass.kubernetes.io/is-default-class: "true"
10 | spec:
11 | controller: bfe-networks.com/ingress-controller
12 |
--------------------------------------------------------------------------------
/test/script/kind-config.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kind.x-k8s.io/v1alpha4
2 | kind: Cluster
3 | nodes:
4 | - role: control-plane
5 | kubeadmConfigPatches:
6 | - |
7 | kind: InitConfiguration
8 | nodeRegistration:
9 | kubeletExtraArgs:
10 | node-labels: "ingress-ready=true"
11 | controllerManager:
12 | extraArgs:
13 | namespace-sync-period: 10s
14 | concurrent-deployment-syncs: "30"
15 | deployment-controller-sync-period: 10s
16 | extraPortMappings:
17 | - containerPort: 30000
18 | hostPort: 30000
19 | protocol: TCP
20 | - containerPort: 30001
21 | hostPort: 30001
22 | protocol: TCP
23 | - role: worker
24 |
--------------------------------------------------------------------------------
/test/script/kind-create-cluster.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright 2022 The BFE Authors
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | set -ex
16 |
17 |
18 | download_kind(){
19 | if [[ "$OSTYPE" == "linux-gnu"* ]]; then
20 | # linux
21 | curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.1/kind-linux-amd64
22 |
23 | elif [[ "$OSTYPE" == "darwin"* ]]; then
24 | # Mac
25 | if [[ $(arch) == 'arm64' ]]; then
26 | curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.1/kind-darwin-arm64
27 | else
28 | curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.1/kind-darwin-amd64
29 | fi
30 | else
31 | echo "unsupported os type: " "$OSTYPE"
32 | exit 1
33 | fi
34 | chmod +x ./kind
35 | }
36 |
37 | cd "$(dirname "$0")"
38 |
39 | if [[ ! -f kind ]]; then
40 | download_kind
41 | fi
42 |
43 | # check if cluster exist
44 | if ./kind get clusters | grep -Fxq "kind"; then
45 | exit 0
46 | fi
47 |
48 | ./kind create cluster --config=./kind-config.yaml
49 |
50 |
51 |
--------------------------------------------------------------------------------
/test/script/kind-delete-cluster.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright 2022 The BFE Authors
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | set -e
16 |
17 | cd "$(dirname "$0")"
18 |
19 | ./kind delete cluster
20 |
--------------------------------------------------------------------------------
/test/script/kind-load-images.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright 2022 The BFE Authors
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | set -e
16 |
17 | cd "$(dirname "$0")"
18 |
19 | # load bfe-ingress-controller image
20 | VERSION=$1
21 | IMAGE="bfenetworks/bfe-ingress-controller:"$VERSION
22 |
23 | if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" ]]; then
24 | echo "image does not exist:" "$IMAGE"
25 | exit 1
26 | fi
27 |
28 | ./kind load docker-image $IMAGE
29 |
30 | # build and load backend image (echoserver)
31 | IMAGE="local/echoserver:0.0.1"
32 |
33 | if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" ]]; then
34 | (cd ../e2e/images/echoserver; make build-image)
35 | fi
36 |
37 | ./kind load docker-image $IMAGE
38 |
--------------------------------------------------------------------------------