├── .build
├── build-e2e-only.yaml
├── build-openresty.yaml
└── build.yaml
├── .cspell.json
├── .dockerignore
├── .editorconfig
├── .github
├── chart
│ └── alb
│ │ └── values.yaml
├── cr.sh
├── cr.yaml
└── workflows
│ ├── alb-perf.yaml
│ ├── build-openresty.yaml
│ └── build.yaml
├── .gitignore
├── .golangci.yml
├── .lua-format
├── .luacheckrc
├── .luacov
├── .luarc.json
├── .vscode
├── README.md
└── launch.json
├── Dockerfile
├── LICENSE.txt
├── README.md
├── catalog
└── alb.yaml
├── cmd
├── alb
│ └── main.go
├── operator
│ └── main.go
└── utils
│ ├── albctl
│ ├── cmd
│ │ ├── debug.go
│ │ ├── log_analyze.go
│ │ ├── log_analyze_test.go
│ │ ├── root.go
│ │ ├── rule.go
│ │ └── rule_test.go
│ └── main.go
│ ├── dirhash
│ └── main.go
│ ├── map_gen
│ └── main.go
│ ├── ngx_gen
│ └── main.go
│ ├── sync_rbac
│ └── main.go
│ ├── tweak_gen
│ └── main.go
│ └── tylua
│ └── main.go
├── config
├── config.go
├── config_ext.go
├── gateway.go
├── mock_config.go
└── types.go
├── controller
├── alb
│ └── alb.go
├── alb2.go
├── cli
│ ├── alb.go
│ ├── cert.go
│ ├── cert_test.go
│ ├── policy.go
│ ├── policy_backend.go
│ ├── policy_l4.go
│ └── policy_l7.go
├── common.go
├── controller_test.go
├── leader.go
├── leader_test.go
├── modules
│ ├── alb2.go
│ └── consts.go
├── nginx.go
├── nginx_test.go
├── patrol.go
├── policy_zip.go
├── portprobe.go
├── portprobe_test.go
├── state
│ └── state.go
├── sync_lb_service.go
└── types
│ ├── consts.go
│ ├── helper.go
│ ├── policyext_test.go
│ └── types.go
├── deploy
├── README.md
├── chart
│ └── alb
│ │ ├── Chart.yaml
│ │ ├── crds
│ │ ├── crd.alauda.io_alaudaloadbalancer2.yaml
│ │ ├── crd.alauda.io_frontends.yaml
│ │ ├── crd.alauda.io_rules.yaml
│ │ ├── gateway.crd.alauda.io_timeoutpolicies.yaml
│ │ └── gateway
│ │ │ ├── gateway.networking.k8s.io_backendtlspolicies.yaml
│ │ │ ├── gateway.networking.k8s.io_gatewayclasses.yaml
│ │ │ ├── gateway.networking.k8s.io_gateways.yaml
│ │ │ ├── gateway.networking.k8s.io_grpcroutes.yaml
│ │ │ ├── gateway.networking.k8s.io_httproutes.yaml
│ │ │ ├── gateway.networking.k8s.io_referencegrants.yaml
│ │ │ ├── gateway.networking.k8s.io_tcproutes.yaml
│ │ │ ├── gateway.networking.k8s.io_tlsroutes.yaml
│ │ │ └── gateway.networking.k8s.io_udproutes.yaml
│ │ ├── module-plugin.yaml
│ │ ├── scripts
│ │ └── plugin-config.yaml
│ │ ├── templates
│ │ ├── acp_dashborad.yaml
│ │ ├── alb.featuregate.yaml
│ │ ├── alb.yaml
│ │ ├── deploy-deployment.yaml
│ │ ├── loadbalancer-service.featuregate.yaml
│ │ ├── operator-clusterrole.yaml
│ │ ├── operator-clusterrolebinding.yaml
│ │ └── operator-sa.yaml
│ │ └── values.yaml
└── resource
│ ├── dashboard
│ └── alb-overview.json
│ └── rbac
│ └── operator-clusterrole.yaml
├── docs
├── README.md
├── _res
│ ├── architecture.png
│ └── common-app.yaml
├── dev-readme.md
├── feature
│ ├── auth
│ │ ├── _res
│ │ │ ├── auth-resty.template
│ │ │ └── basic-auth.svg
│ │ ├── auth-eng.md
│ │ ├── auth.md
│ │ ├── dev_readme.md
│ │ ├── 测试用例.md
│ │ └── 配置oauth2-proxy.md
│ ├── containermode
│ │ └── api-containermode-gateway-deploy.md
│ ├── errorpage
│ │ └── errorpage.md
│ ├── ingressclass
│ │ └── api-ingressclass.md
│ ├── keepalive
│ │ ├── app.yaml
│ │ └── testcase.md
│ ├── modsecurity
│ │ ├── modsecurity.en.md
│ │ └── modsecurity.md
│ ├── otel
│ │ ├── _res
│ │ │ ├── alb-otel.drawio.svg
│ │ │ ├── jaeger.png
│ │ │ └── trace.png
│ │ └── otel.md
│ ├── redirect
│ │ ├── app.yaml
│ │ └── testcase.md
│ ├── rule
│ │ └── rules.md
│ └── timeout
│ │ ├── app.yaml
│ │ └── testcase.md
├── flags
│ └── cert.md
└── release-note
│ └── README.md
├── driver
├── alb2.go
├── constants.go
├── driver.go
├── driver_test.go
├── informers.go
└── kubernetes.go
├── gateway
├── constant.go
├── ctl
│ ├── common_filter.go
│ ├── constants.go
│ ├── driver.go
│ ├── gateway.go
│ ├── gateway_class.go
│ ├── hostname_filter.go
│ ├── hostname_filter_test.go
│ ├── reservedPortFilter.go
│ ├── setup.go
│ ├── types.go
│ ├── util.go
│ ├── watches_alb.go
│ └── watches_router.go
├── nginx
│ ├── driver.go
│ ├── http
│ │ ├── httproute.go
│ │ ├── httproute_filter.go
│ │ ├── httproute_filter_test.go
│ │ ├── httproute_test.go
│ │ └── utils.go
│ ├── nginx.go
│ ├── policyattachment
│ │ ├── common.go
│ │ ├── manager.go
│ │ ├── timeout_policy.go
│ │ ├── timeout_policy_test.go
│ │ └── types
│ │ │ └── types.go
│ ├── tcp.go
│ ├── types
│ │ └── types.go
│ ├── udp.go
│ └── utils
│ │ └── utils.go
├── utils.go
└── utils
│ └── hostname.go
├── go.mod
├── go.sum
├── ingress
├── const.go
├── driver.go
├── ingress_controller.go
├── ingress_select.go
├── ingress_status.go
├── ingress_status_test.go
├── ingress_sync.go
├── ingress_sync_test.go
├── ingress_test.go
├── need.go
├── project.go
├── resync.go
├── resync_test.go
├── util.go
└── util
│ ├── util.go
│ └── util_test.go
├── migrate
├── backup
│ └── backup.sh
├── checklist
│ ├── README.md
│ ├── custom
│ │ ├── alb
│ │ │ └── check_cm
│ │ │ │ └── cm_map
│ │ │ │ ├── v3.0
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream
│ │ │ │ └── upstream
│ │ │ │ ├── v3.10
│ │ │ │ ├── grpc_server
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream-common
│ │ │ │ ├── stream-tcp
│ │ │ │ ├── stream-udp
│ │ │ │ └── upstream
│ │ │ │ ├── v3.4
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream
│ │ │ │ └── upstream
│ │ │ │ ├── v3.6.0
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream
│ │ │ │ └── upstream
│ │ │ │ ├── v3.6.9
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream
│ │ │ │ └── upstream
│ │ │ │ ├── v3.8.0
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream-common
│ │ │ │ ├── stream-tcp
│ │ │ │ ├── stream-udp
│ │ │ │ └── upstream
│ │ │ │ └── v3.8.13
│ │ │ │ ├── http
│ │ │ │ ├── http_server
│ │ │ │ ├── stream-common
│ │ │ │ ├── stream-tcp
│ │ │ │ ├── stream-udp
│ │ │ │ └── upstream
│ │ └── check-alb.sh
│ ├── helper.sh
│ ├── run.sh
│ └── test.sh
├── init-port-info
│ ├── README.md
│ └── main.go
├── priority
│ ├── README.md
│ └── main.go
└── v26tov28
│ ├── README.md
│ └── main.go
├── pkg
├── apis
│ └── alauda
│ │ ├── gateway
│ │ └── v1alpha1
│ │ │ ├── doc.go
│ │ │ ├── register.go
│ │ │ ├── types.go
│ │ │ └── zz_generated.deepcopy.go
│ │ ├── shared
│ │ ├── cr.go
│ │ └── zz_generated.deepcopy.go
│ │ ├── v1
│ │ ├── doc.go
│ │ ├── register.go
│ │ ├── types.go
│ │ └── zz_generated.deepcopy.go
│ │ └── v2beta1
│ │ ├── alb2_types.go
│ │ ├── doc.go
│ │ ├── groupversion_info.go
│ │ └── zz_generated.deepcopy.go
├── client
│ ├── clientset
│ │ └── versioned
│ │ │ ├── clientset.go
│ │ │ ├── doc.go
│ │ │ ├── fake
│ │ │ ├── clientset_generated.go
│ │ │ ├── doc.go
│ │ │ └── register.go
│ │ │ ├── scheme
│ │ │ ├── doc.go
│ │ │ └── register.go
│ │ │ └── typed
│ │ │ ├── alauda
│ │ │ ├── v1
│ │ │ │ ├── alauda_client.go
│ │ │ │ ├── alb2.go
│ │ │ │ ├── doc.go
│ │ │ │ ├── fake
│ │ │ │ │ ├── doc.go
│ │ │ │ │ ├── fake_alauda_client.go
│ │ │ │ │ ├── fake_alb2.go
│ │ │ │ │ ├── fake_frontend.go
│ │ │ │ │ └── fake_rule.go
│ │ │ │ ├── frontend.go
│ │ │ │ ├── generated_expansion.go
│ │ │ │ └── rule.go
│ │ │ └── v2beta1
│ │ │ │ ├── alauda_client.go
│ │ │ │ ├── alb2.go
│ │ │ │ ├── doc.go
│ │ │ │ ├── fake
│ │ │ │ ├── doc.go
│ │ │ │ ├── fake_alauda_client.go
│ │ │ │ └── fake_alb2.go
│ │ │ │ └── generated_expansion.go
│ │ │ └── gateway
│ │ │ └── v1alpha1
│ │ │ ├── doc.go
│ │ │ ├── fake
│ │ │ ├── doc.go
│ │ │ ├── fake_gateway_client.go
│ │ │ └── fake_timeoutpolicy.go
│ │ │ ├── gateway_client.go
│ │ │ ├── generated_expansion.go
│ │ │ └── timeoutpolicy.go
│ ├── informers
│ │ └── externalversions
│ │ │ ├── alauda
│ │ │ ├── interface.go
│ │ │ ├── v1
│ │ │ │ ├── alb2.go
│ │ │ │ ├── frontend.go
│ │ │ │ ├── interface.go
│ │ │ │ └── rule.go
│ │ │ └── v2beta1
│ │ │ │ ├── alb2.go
│ │ │ │ └── interface.go
│ │ │ ├── factory.go
│ │ │ ├── gateway
│ │ │ ├── interface.go
│ │ │ └── v1alpha1
│ │ │ │ ├── interface.go
│ │ │ │ └── timeoutpolicy.go
│ │ │ ├── generic.go
│ │ │ └── internalinterfaces
│ │ │ └── factory_interfaces.go
│ └── listers
│ │ ├── alauda
│ │ ├── v1
│ │ │ ├── alb2.go
│ │ │ ├── expansion_generated.go
│ │ │ ├── frontend.go
│ │ │ └── rule.go
│ │ └── v2beta1
│ │ │ ├── alb2.go
│ │ │ └── expansion_generated.go
│ │ └── gateway
│ │ └── v1alpha1
│ │ ├── expansion_generated.go
│ │ └── timeoutpolicy.go
├── config
│ ├── albrun.go
│ └── const.go
├── controller
│ ├── ext
│ │ ├── auth
│ │ │ ├── auth.go
│ │ │ ├── auth_test.go
│ │ │ ├── basic_auth.go
│ │ │ ├── forward_auth.go
│ │ │ ├── types
│ │ │ │ ├── codegen_mapping.go
│ │ │ │ ├── types.go
│ │ │ │ └── zz_generated.deepcopy.go
│ │ │ └── util.go
│ │ ├── keepalive
│ │ │ ├── keepalive.go
│ │ │ ├── test
│ │ │ │ └── keepalive_test.go
│ │ │ └── types
│ │ │ │ ├── types.go
│ │ │ │ └── zz_generated.deepcopy.go
│ │ ├── otel
│ │ │ ├── otel.go
│ │ │ ├── test
│ │ │ │ └── otel_test.go
│ │ │ └── types
│ │ │ │ ├── type.go
│ │ │ │ └── zz_generated.deepcopy.go
│ │ ├── redirect
│ │ │ ├── redirect.go
│ │ │ ├── test
│ │ │ │ └── redirect_test.go
│ │ │ └── types
│ │ │ │ ├── codegen_mapping.go
│ │ │ │ ├── type.go
│ │ │ │ └── zz_generated.deepcopy.go
│ │ ├── timeout
│ │ │ ├── test
│ │ │ │ └── timeout_test.go
│ │ │ ├── timeout.go
│ │ │ └── types
│ │ │ │ ├── codegen_mapping.go
│ │ │ │ ├── type.go
│ │ │ │ └── zz_generated.deepcopy.go
│ │ └── waf
│ │ │ ├── test
│ │ │ └── waf_test.go
│ │ │ ├── types
│ │ │ ├── waf_type.go
│ │ │ └── zz_generated.deepcopy.go
│ │ │ └── waf.go
│ ├── extctl
│ │ ├── extctl.go
│ │ ├── extctl_test.go
│ │ ├── header_moidy_ctl.go
│ │ ├── header_moidy_ctl_test.go
│ │ ├── legacy.go
│ │ └── types
│ │ │ └── type.go
│ └── ngxconf
│ │ ├── nginx.tmpl
│ │ ├── nginx_param.go
│ │ ├── ngxconf.go
│ │ ├── ngxconf_tmpl.go
│ │ ├── ngxconf_tmpl_test.go
│ │ ├── test
│ │ └── ngxconf_test.go
│ │ └── types
│ │ └── types.go
├── operator
│ ├── .dockerignore
│ ├── .gitignore
│ ├── config
│ │ ├── config_test.go
│ │ ├── const.go
│ │ ├── external.go
│ │ ├── external_test.go
│ │ ├── internal.go
│ │ └── operator.go
│ ├── controllers
│ │ ├── depl
│ │ │ ├── alb_cli.go
│ │ │ ├── alb_overwrite_configmap.go
│ │ │ ├── alb_reconciler.go
│ │ │ ├── alb_status.go
│ │ │ ├── current.go
│ │ │ ├── depl_ctl.go
│ │ │ ├── depl_test.go
│ │ │ ├── handle_backup_annotation.go
│ │ │ ├── patch
│ │ │ │ ├── configmap_patch.go
│ │ │ │ └── image_patch.go
│ │ │ ├── resources
│ │ │ │ ├── configmap
│ │ │ │ │ ├── configmap.go
│ │ │ │ │ ├── const.go
│ │ │ │ │ └── options.go
│ │ │ │ ├── feature
│ │ │ │ │ └── feature.go
│ │ │ │ ├── gateway
│ │ │ │ │ ├── gatewayclass.go
│ │ │ │ │ └── options.go
│ │ │ │ ├── ingressclass
│ │ │ │ │ ├── ingcls_ctl.go
│ │ │ │ │ └── ingcls_ctl_test.go
│ │ │ │ ├── portinfo
│ │ │ │ │ ├── options.go
│ │ │ │ │ └── portinfo.go
│ │ │ │ ├── rbac
│ │ │ │ │ ├── alb-clusterrole.json
│ │ │ │ │ ├── rbac.go
│ │ │ │ │ └── rbac_test.go
│ │ │ │ ├── service
│ │ │ │ │ ├── svcctl.go
│ │ │ │ │ └── svcctl_test.go
│ │ │ │ ├── types
│ │ │ │ │ └── types.go
│ │ │ │ └── workload
│ │ │ │ │ ├── deploy.go
│ │ │ │ │ ├── deploy_test.go
│ │ │ │ │ └── options.go
│ │ │ ├── suite_test.go
│ │ │ └── util
│ │ │ │ └── util.go
│ │ ├── init.go
│ │ ├── scheme.go
│ │ ├── setup.go
│ │ ├── standalone_gateway
│ │ │ ├── gateway
│ │ │ │ ├── cli_ext.go
│ │ │ │ └── reconciler.go
│ │ │ └── gatewayclass
│ │ │ │ └── reconciler.go
│ │ ├── suite_test.go
│ │ └── types
│ │ │ └── const.go
│ └── toolkit
│ │ ├── clustertype.go
│ │ ├── meta.go
│ │ ├── tools.go
│ │ └── tools_test.go
└── utils
│ ├── data_trans.go
│ ├── metrics
│ └── metrics.go
│ ├── test_utils
│ ├── ing_utils
│ │ └── ing.go
│ ├── mock_svc.go
│ ├── ngx_conf.go
│ ├── ngxconf_parser_ext_test.go
│ ├── policy_assert.go
│ └── policy_helper.go
│ └── util.go
├── run-alb.sh
├── scripts
├── alb-ai-actions.sh
├── alb-build-actions.sh
├── alb-checklist-actions.sh
├── alb-codegen-actions.sh
├── alb-debug-actions.sh
├── alb-dev-actions.sh
├── alb-env-actions.sh
├── alb-github-actions.sh
├── alb-lint-actions.sh
├── alb-perf-actions.sh
├── alb-test-actions.sh
├── boilerplate.go.txt
├── custom-ci-action.sh
├── go-test.sh
├── kubescape.js
├── nginx-test.sh
├── rule-gen.py
├── run-like-ci-go.sh
├── run-like-ci-kind.sh
├── run-like-ci-nginx.sh
├── run-like-github-actions.sh
├── tmuxs
│ └── fg.tmux.json
└── yaml
│ └── crds
│ ├── extra
│ ├── mock
│ │ ├── cluster.yaml
│ │ └── clustercert.yaml
│ ├── v1
│ │ ├── apprelease.yaml
│ │ ├── csv.crd.yaml
│ │ ├── features.crd.yaml
│ │ └── hr.crd.yaml
│ └── v1beta1
│ │ └── features.crd.yaml
│ ├── v1
│ └── alb
│ │ ├── crd.alauda.io_alaudaloadbalancer2.yaml
│ │ ├── crd.alauda.io_frontends.yaml
│ │ └── crd.alauda.io_rules.yaml
│ └── v1beta1
│ ├── alb2-crd.yaml
│ ├── features.crd.yaml
│ ├── frontend-crd.yaml
│ └── rule-crd.yaml
├── sonar-project.properties
├── template
├── Dockerfile.debug
├── Dockerfile.openresty
├── README.md
├── actions
│ ├── alb-nginx-install-deps.sh
│ ├── alb-nginx.sh
│ ├── dev.actions.sh
│ └── test-nginx-in-ci.sh
├── chaos
│ ├── break
│ │ ├── README.md
│ │ ├── alb.nginx.conf
│ │ ├── policy.json
│ │ └── server.py
│ └── tl502
│ │ ├── README.md
│ │ ├── demo.conf
│ │ ├── server.py
│ │ ├── test.lua
│ │ ├── test.t
│ │ └── x.lua
├── nginx
│ ├── lua
│ │ ├── README.md
│ │ ├── balancer
│ │ │ ├── alb_chash.lua
│ │ │ ├── balance.lua
│ │ │ ├── common.lua
│ │ │ ├── resty.lua
│ │ │ ├── round_robin.lua
│ │ │ ├── sticky.lua
│ │ │ └── sticky_balanced.lua
│ │ ├── cert_tool.lua
│ │ ├── config
│ │ │ ├── README.md
│ │ │ ├── cache.lua
│ │ │ ├── conf.lua
│ │ │ ├── policy_fetch.lua
│ │ │ └── shmap.lua
│ │ ├── cors.lua
│ │ ├── ctx
│ │ │ ├── alb_ctx.lua
│ │ │ └── var_proxy.lua
│ │ ├── error.lua
│ │ ├── l4_preread.lua
│ │ ├── l7_redirect.lua
│ │ ├── match_engine
│ │ │ ├── dsl.lua
│ │ │ ├── operation.lua
│ │ │ └── upstream.lua
│ │ ├── metrics.lua
│ │ ├── metrics_auth.lua
│ │ ├── phase
│ │ │ ├── balancer_phase.lua
│ │ │ ├── init_worker_phase.lua
│ │ │ ├── l7_header_filter_phase.lua
│ │ │ ├── l7_rewrite_phase.lua
│ │ │ ├── log_phase.lua
│ │ │ └── ssl_cert_phase.lua
│ │ ├── plugins
│ │ │ ├── auth
│ │ │ │ ├── auth.lua
│ │ │ │ ├── basic_auth.lua
│ │ │ │ ├── buffer_md5.lua
│ │ │ │ ├── crypt.lua
│ │ │ │ └── forward_auth.lua
│ │ │ ├── core
│ │ │ │ └── plugin_manager.lua
│ │ │ ├── otel
│ │ │ │ ├── otel.lua
│ │ │ │ ├── tool.lua
│ │ │ │ ├── tracer.lua
│ │ │ │ └── tracer_http_client.lua
│ │ │ └── timeout.lua
│ │ ├── replace_prefix_match.lua
│ │ ├── rewrite_header.lua
│ │ ├── types
│ │ │ ├── common.lua
│ │ │ ├── ngxpolicy.types.lua
│ │ │ └── vendor.lua
│ │ ├── utils
│ │ │ ├── common.lua
│ │ │ ├── compress.lua
│ │ │ ├── generic_ext.lua
│ │ │ ├── ip.lua
│ │ │ ├── numer_ext.lua
│ │ │ ├── string_ext.lua
│ │ │ ├── subsystem.lua
│ │ │ └── url.lua
│ │ └── vendor
│ │ │ ├── events.lua
│ │ │ ├── lua-ffi-zlib
│ │ │ ├── LICENSE.txt
│ │ │ ├── README.md
│ │ │ ├── dist.ini
│ │ │ ├── lib
│ │ │ │ └── ffi-zlib.lua
│ │ │ ├── lua-ffi-zlib-0.4-0.rockspec
│ │ │ ├── lua-ffi-zlib-0.5-0.rockspec
│ │ │ └── test.lua
│ │ │ └── prometheus
│ │ │ ├── prometheus.lua
│ │ │ ├── prometheus_keys.lua
│ │ │ └── prometheus_resty_counter.lua
│ ├── nginx.conf
│ ├── policy.example.json
│ └── run-nginx.sh
└── t
│ ├── Alauda.pm
│ ├── AlaudaLib.pm
│ ├── AlaudaTest.pm
│ ├── balancer.t
│ ├── balancer_test.lua
│ ├── common.t
│ ├── cors.t
│ ├── e2e
│ ├── auth_test
│ │ ├── auth_test.lua
│ │ └── auth_test.t
│ ├── cert
│ │ ├── cert.lua
│ │ └── cert.t
│ ├── error_page
│ │ ├── error.lua
│ │ └── error.t
│ ├── https_upgrade
│ │ ├── test.lua
│ │ └── test.t
│ ├── metrics
│ │ ├── metrics.lua
│ │ └── metrics.t
│ ├── ping
│ │ ├── ping.lua
│ │ └── ping.t
│ ├── retry_test
│ │ ├── retry_test.lua
│ │ └── retry_test.t
│ ├── rewrite_request
│ │ ├── test.lua
│ │ └── test.t
│ ├── rule_match
│ │ ├── rule.lua
│ │ └── rule.t
│ ├── timeout_test
│ │ ├── timeout_test.lua
│ │ └── timeout_test.t
│ ├── trace
│ │ ├── trace.lua
│ │ └── trace.t
│ └── waf
│ │ ├── waf.lua
│ │ └── waf.t
│ ├── l7_redirect.t
│ ├── lib
│ ├── F.lua
│ ├── inspect.lua
│ ├── mock_worker_init.lua
│ ├── policy_helper.lua
│ ├── test-helper.lua
│ └── util.lua
│ ├── manually
│ ├── fortio
│ │ ├── fortio.lua
│ │ └── fortio.perf
│ ├── nyi
│ │ ├── nyi
│ │ └── nyi.lua
│ └── otel_test
│ │ ├── otel_test
│ │ └── otel_test.lua
│ ├── matches.t
│ ├── nignx_config.t
│ ├── ping.t
│ ├── proxy-paas-between-https-and-http.t
│ ├── resource
│ ├── policy.bin
│ ├── policy.bin.empty
│ └── policy.bin.invalid
│ ├── rewrite_response.t
│ ├── timeout.ignore
│ ├── udp.t
│ ├── unit
│ ├── cert_test.lua
│ ├── common_test.lua
│ ├── cors_test.lua
│ ├── plugins
│ │ └── auth
│ │ │ └── auth_unit_test.lua
│ ├── replace_prefix_match_test.lua
│ ├── unit_test.lua
│ └── unit_test.t
│ ├── url_rewrite.t
│ └── zip.t
├── test
├── README.md
├── alauda
│ └── README.md
├── checklist
│ ├── alb.go
│ ├── apprelease.yaml
│ ├── hr.yaml
│ └── suite_test.go
├── conformance
│ ├── gatewayapi
│ │ └── suite_test.go
│ └── ingress-nginx
│ │ ├── README.md
│ │ ├── auth.go
│ │ ├── auth_kind.sh
│ │ ├── auth_resty.go
│ │ ├── lua_snip
│ │ ├── app.lua
│ │ ├── auth.lua
│ │ └── state.lua
│ │ └── suite_test.go
├── e2e
│ ├── alb
│ │ └── alb.go
│ ├── cases
│ │ └── cases.go
│ ├── framework
│ │ ├── alb_assert_ext.go
│ │ ├── alb_operator_ext.go
│ │ ├── albenv.go
│ │ ├── albwaitfile_ext.go
│ │ ├── consts.go
│ │ ├── gateway_assert_ext.go
│ │ ├── ingress_assert_ext.go
│ │ ├── operator_env.go
│ │ ├── product_ns.go
│ │ ├── suite_helper.go
│ │ ├── svc_ext_.go
│ │ ├── tls.go
│ │ └── util.go
│ ├── gateway
│ │ ├── common.go
│ │ ├── http.go
│ │ ├── policyattachment
│ │ │ └── timeout_policy.go
│ │ ├── shared_gateway.go
│ │ ├── standalone_gateway.go
│ │ ├── tcp.go
│ │ └── udp.go
│ ├── ingress
│ │ ├── all.ingress
│ │ ├── ingress.go
│ │ └── rule_sync.go
│ ├── operator
│ │ ├── README.md
│ │ ├── alb
│ │ │ └── basic.go
│ │ ├── gateway
│ │ │ └── gateway.go
│ │ ├── public-cloud
│ │ │ └── cce.go
│ │ ├── rawk8s
│ │ │ └── raw.go
│ │ └── simple
│ │ │ ├── basic.go
│ │ │ ├── chart.go
│ │ │ ├── operator.go
│ │ │ ├── patch.go
│ │ │ └── update.go
│ ├── perf
│ │ └── perf.go
│ ├── rule-perf-cpu
│ └── suite_test.go
└── kind
│ ├── e2e
│ ├── gateway
│ │ └── gateway.go
│ ├── operator
│ │ └── operator.go
│ ├── qps_test.go
│ └── suite_test.go
│ └── pkg
│ └── helper
│ ├── alb-chart-ext.go
│ ├── alb-chart-ext_test.go
│ ├── alb-ctx.go
│ ├── echo-resty-ext.go
│ ├── echo-resty.yaml
│ ├── echo-resty_test.go
│ ├── king-gc.go
│ ├── king-gc_test.go
│ └── qps
│ ├── assert.go
│ ├── curl.go
│ ├── keep-curl.go
│ └── keep-curl_test.go
├── timestamp.txt
└── utils
├── address.go
├── client
└── client.go
├── consts.go
├── dirhash
├── hash.go
└── hash_test.go
├── dsl.go
├── dsl_test.go
├── log
├── log.go
└── log_test.go
├── net_utils.go
├── string_ext.go
├── string_ext_test.go
├── test_utils
├── assert
│ ├── alb.go
│ ├── deployment.go
│ └── ingress.go
├── assert_cr_helper.go
├── command.go
├── console_logger.go
├── docker-ext.go
├── docker-ext_test.go
├── envtest_ext.go
├── eq.go
├── fake_alb_env.go
├── fake_alb_env_test.go
├── faker.go
├── ginkgo_ext.go
├── ginkgo_logger.go
├── helm_ext.go
├── initer.go
├── json.go
├── k8s_client_ext.go
├── kind-ext.go
├── kind-ext_test.go
├── kubectl_ext.go
├── metallb_ext.go
├── mocklbsvc.go
├── util.go
├── util_test.go
├── yq.go
└── yq_test.go
├── types.go
├── util.go
├── wait.go
└── wait_test.go
/.dockerignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | alauda_lb
3 | alauda_lb.iml
4 | .git/test/e2e/viper-config.toml
5 |
--------------------------------------------------------------------------------
/.github/chart/alb/values.yaml:
--------------------------------------------------------------------------------
1 | ## global
2 | operator:
3 | albImagePullPolicy: IfNotPresent
4 | defaultAlb: false # 部署默认的alb
5 | operatorReplicas: 1
6 | operatorDeployMode: "deployment" # csv|deployment
7 | global:
8 | labelBaseDomain: cpaas.io
9 | namespace: kube-system
10 | registry:
11 | address: theseedoaa
12 | images:
13 | alb2:
14 | code: https://github.com/alauda/alb
15 | support_arm: true
16 | repository: alb
17 | nginx:
18 | code: https://github.com/alauda/alb
19 | support_arm: true
20 | repository: alb
21 | resources:
22 | alb:
23 | limits:
24 | cpu: "200m"
25 | memory: 2Gi
26 | requests:
27 | cpu: 50m
28 | memory: 128Mi
29 | limits:
30 | cpu: "2"
31 | memory: 2Gi
32 | requests:
33 | cpu: 50m
34 | memory: 128Mi
35 |
--------------------------------------------------------------------------------
/.github/cr.yaml:
--------------------------------------------------------------------------------
1 | sign: false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Example user template template
3 | ### Example user template
4 |
5 | # IntelliJ project files
6 | .idea
7 | *.iml
8 | out
9 | gen
10 | config/haproxy/*
11 | alb2
12 | migrate_priority
13 | migrate_v26tov28
14 | *.DS_Store
15 | haproxy.cfg.new
16 | policy.new
17 | VERSION
18 | test.json
19 | coverage-all.out
20 | alb-nginx/luacov.stats.out
21 | temp/
22 | .wc/
23 | scripts/e2e/.tmp
24 | .scannerwork
25 | alb-nginx/t/servroot
26 | alb-nginx/t/.nvimlog
27 | tweak
28 | scripts/loop.sh
29 | alb-nginx/actions/loop.sh
30 | bin
31 | .alb.local
32 | test/e2e/alb-config.toml
33 | *.log
34 | .vscode/settings.json
35 | test/e2e/*.test
36 | test/e2e/*/*.test
37 | test/e2e/*/*/*.test
38 | cmds.cfg
39 | .t/
40 | loop.sh
41 | alauda-alb2/
42 | coverage.*
43 | deploy/operator/bundle
44 | deploy/operator/bundle.Dockerfile
45 | .test/
46 | template/servroot
47 | template/dhparam.pem
48 | template/policy.new
49 | template/nginx/logs
50 | template/logs
51 | template/cert
52 | alb-kind-e2e
53 | test.test
54 | migrate/checklist/.kube/
55 | kubectl*
56 | fortio/*.json
57 | .flame/
58 | template/nginx/lua/vendor/opentelemetry
59 | *.kconf
60 | docs/.obsidian
61 | template/share/dhparam.pem
62 | luacov-html/
63 | luacov.stats.out
64 | luacov.report.out
65 | luacov.report.out.index
66 | luacov.summary
67 | .kube
68 | .fg
69 | .review/
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | run:
2 | timeout: 4600s
3 | skip-dirs:
4 | - test
5 | linters:
6 | enable:
7 | - gocritic
8 | - gofumpt
9 | - goimports
10 | - misspell
11 | - predeclared
12 | - revive
13 | - unconvert
14 | - unused
15 | issues:
16 | exclude-rules:
17 | - linters:
18 | - staticcheck
19 | text: "SA1019:" # gateway status deprecated. gv1.GatewayReasonReady is deprecated: Ready is reserved for future use
20 | - path: _test\.go
21 | linters:
22 | - errcheck
23 | linters-settings:
24 | errcheck:
25 | check-blank: true
26 | gocritic:
27 | disabled-checks:
28 | - ifElseChain
29 | - singleCaseSwitch
30 | - badCond
31 | revive:
32 | rules:
33 | - name: var-naming
34 | severity: warning
35 | disabled: true
--------------------------------------------------------------------------------
/.lua-format:
--------------------------------------------------------------------------------
1 | use_tab: false
2 | keep_simple_control_block_one_line: false
3 | line-breaks-after-function-body: false
4 | keep_simple_function_one_line: false
5 | column_limit: 380
6 | chop_down_table: true
7 |
--------------------------------------------------------------------------------
/.luacheckrc:
--------------------------------------------------------------------------------
1 | std = 'ngx_lua'
2 | codes = true
3 | max_line_length = false
4 | globals = {
5 | 'ngx', 'ndk',
6 | }
7 | ignore= {"411","421","431"}
8 | read_globals = {
9 | "coroutine._yield"
10 | }
11 | exclude_files = {"template/nginx/lua/vendor/**"}
--------------------------------------------------------------------------------
/.luacov:
--------------------------------------------------------------------------------
1 | reporter = "html"
2 | html = {}
3 | include = {
4 | ".*/template/nginx/lua/.*"
5 | }
6 | exclude = {
7 | ".*/template/nginx/lua/vendor/.*",
8 | }
9 |
--------------------------------------------------------------------------------
/.luarc.json:
--------------------------------------------------------------------------------
1 | {
2 | "runtime": {
3 | "version": "Lua 5.1",
4 | "path": [
5 | "?.lua",
6 | "?/init.lua",
7 | "./template/nginx/lua/?.lua",
8 | "./template/nginx/lua/vendor/?.lua"
9 | ]
10 | },
11 | "diagnostics": {
12 | "ignoredFiles": "Disable",
13 | "libraryFiles": "Disable",
14 | "globals": [
15 | "vim",
16 | "use",
17 | "ngx",
18 | "jit",
19 | "_ENV"
20 | ]
21 | },
22 | "workspace": {
23 | "ignoreDir": [
24 | ".vscode",
25 | "work-park",
26 | "vendor"
27 | ],
28 | "library": [
29 | "${3rd}/OpenResty/library"
30 | ]
31 | }
32 | }
--------------------------------------------------------------------------------
/.vscode/README.md:
--------------------------------------------------------------------------------
1 | # recommend plugins
2 | ```bash
3 | code --install-extension sumneko.lua
4 |
5 | ```
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "operator",
6 | "type": "go",
7 | "request": "launch",
8 | "mode": "exec",
9 | "env": {
10 | "USE_KUBE_CONFIG": "/home/cong/.kube/gw",
11 | "LEADER_NS": "cpaas-system",
12 | "ALB_IMAGE": "registry.alauda.cn:60080/acp/alb2:v3.14.1",
13 | "NGINX_IMAGE": "registry.alauda.cn:60080/acp/alb-nginx:v3.14.1",
14 | "VERSION": "v3.14.1",
15 | "LABEL_BASE_DOMAIN": "cpaas.io",
16 | },
17 | "program": "operator"
18 | },
19 | {
20 | // use FIT to focus
21 | "name": "ginkgo envtest",
22 | "type": "go",
23 | "request": "launch",
24 | "mode": "test",
25 | "args": [
26 | "-ginkgo.failFast",
27 | ],
28 | "program": "${workspaceFolder}/test/e2e",
29 | },
30 | {
31 | "name": "ginkgo conformance",
32 | "type": "go",
33 | "request": "launch",
34 | "mode": "test",
35 | "args": [
36 | "-ginkgo.failFast",
37 | ],
38 | "program": "${workspaceFolder}/test/conformance",
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/catalog/alb.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: alb
5 | description: alauda loadbalancer controller
6 | annotations:
7 | # gitlab 仓库地址,格式:${group}/${name}
8 | gitlab.com/project-slug: container-platform/alb2
9 | gitlab.com/instance: gitlab-ce.alauda.cn
10 |
11 | # acp ci 流水线地址,格式:${project}/${cluster}/${ns}/${name}
12 | # 文档地址: https://dp.alauda.cn/docs/default/component/developer-platform/plugins/dp-cicd/#for-developer
13 | # 如果有多个流水线,用逗号分隔
14 | acp.cpaas.io/ci-pipeline: acp/business-build/acp-dev/alb
15 |
16 | # harbor 仓库信息,格式:${project}/${repo}
17 | # 如果有多个仓库,用逗号分隔
18 | goharbor.io/repository-slug: acp/alb2,acp/alb-nginx
19 |
20 | # sonarqube 项目信息(projectKey)。比如下面的 sonar 项目地址,projectKey 为 gitlab-ce.alauda.cn-developer-platform-octopus
21 | # https://build-sonar.alauda.cn/dashboard?id=gitlab-ce.alauda.cn-developer-platform-octopus
22 | sonarqube.org/project-key: gitlab-ce.alauda.cn-container-platform-alb2
23 |
24 | # 组件的管理人员,格式 ${owner}
25 | acp.cpaas.io/owner: congwu@alauda.io
26 | acp.cpaas.io/functional-attributes: core
27 | # 技术文档目录,相对于 catalog-info.yaml 文件 mkdocs.yaml 所在的位置。比如下面的目录结构,技术文档目录为 ./
28 | # .
29 | # ├── mkdocs.mk
30 | # ├── catalog-info.yaml
31 | backstage.io/techdocs-ref: dir:./
32 | spec:
33 | # 组件属于什么类型
34 | type: service
35 | # 组件属于什么生命周期,可选值{"experimental":"试验阶段","production":"维护阶段","deprecated":"周期末尾阶段,稍后回收"}
36 | lifecycle: production
37 | # 组件所属团队
38 | owner: ACP
39 |
--------------------------------------------------------------------------------
/cmd/utils/albctl/cmd/debug.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "time"
7 |
8 | "github.com/spf13/cobra"
9 | )
10 |
11 | // case1. rule has no ep
12 | // case2. rule start with /
13 |
14 | var debug = &cobra.Command{
15 | Use: "debug",
16 | Short: "auto debug",
17 | RunE: func(cmd *cobra.Command, args []string) error {
18 | ctx := cmd.Context()
19 | now := time.Now()
20 | defer func() {
21 | fmt.Printf("over spend %v\n", time.Since(now))
22 | }()
23 | return autodebug(ctx)
24 | },
25 | }
26 |
27 | func autodebug(ctx context.Context) error {
28 | return nil
29 | }
30 |
31 | func init() {
32 | rootCmd.AddCommand(debug)
33 | }
34 |
--------------------------------------------------------------------------------
/cmd/utils/albctl/cmd/log_analyze_test.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestParse(t *testing.T) {
9 | lines := []string{
10 | `[14/Oct/2024:07:11:12 +0000] 158.246.10.93 "158.246.0.58" "POST /mfs/channel/http.do HTTP/1.1" 200 504 200 "158.246.9.68:9080,158.246.9.160:9080" "Apache-HttpClient/4.5.7 (Java/1.8.0_322)" "158.219.208.229, 158.246.0.82" 5.035 5.000,0.035`,
11 | `[14/Oct/2024:07:11:12 +0000] 158.246.10.93 "158.246.0.58" "POST /mfs/channel/http.do HTTP/1.1" 200 504, 200 158.246.9.68:9080, 158.246.9.160:9080 "Apache-HttpClient/4.5.7 (Java/1.8.0_322)" "158.219.208.229, 158.246.0.82" 5.035 5.000, 0.035`,
12 | }
13 | for _, l := range lines {
14 | fmt.Printf("%+v", ParseItHarder(l))
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/cmd/utils/albctl/cmd/root.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "fmt"
5 | "os"
6 |
7 | "github.com/spf13/cobra"
8 | )
9 |
10 | type GlobalOpt struct {
11 | KubecfgPath string
12 | }
13 |
14 | var GOpt = GlobalOpt{}
15 |
16 | // rootCmd represents the base command when called without any subcommands
17 | var rootCmd = &cobra.Command{
18 | Use: "albctl",
19 | PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
20 | if GOpt.KubecfgPath != "" {
21 | return nil
22 | }
23 | env := os.Getenv("KUBECONFIG")
24 | if env != "" {
25 | GOpt.KubecfgPath = env
26 | }
27 | defaultPath := os.Getenv("HOME") + "/.kube/config"
28 | _, err := os.Stat(defaultPath)
29 | if GOpt.KubecfgPath == "" && err == nil {
30 | GOpt.KubecfgPath = defaultPath
31 | }
32 | if GOpt.KubecfgPath == "" {
33 | return fmt.Errorf("need kubecfg path")
34 | }
35 | return nil
36 | },
37 | Short: "debug util for alb",
38 | }
39 |
40 | func Execute() {
41 | if err := rootCmd.Execute(); err != nil {
42 | os.Exit(1)
43 | }
44 | }
45 |
46 | func init() {
47 | }
48 |
--------------------------------------------------------------------------------
/cmd/utils/albctl/cmd/rule_test.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "context"
5 | "os"
6 | "testing"
7 |
8 | "alauda.io/alb2/config"
9 | "alauda.io/alb2/driver"
10 | . "alauda.io/alb2/pkg/utils/test_utils"
11 | lu "alauda.io/alb2/utils"
12 | "alauda.io/alb2/utils/log"
13 | "github.com/stretchr/testify/assert"
14 | )
15 |
16 | func TestPolicyInReal(t *testing.T) {
17 | if os.Getenv("TestPolicyInReal") == "" {
18 | return
19 | }
20 | ctx := context.Background()
21 | mock := config.DefaultMock()
22 | l := log.L()
23 | kconf, err := driver.GetKubeCfgFromFile(os.Getenv("KUBECONFIG"))
24 | assert.NoError(t, err)
25 | drv, err := driver.NewDriver(driver.DrvOpt{Ctx: ctx, Cf: kconf, Opt: driver.Cfg2opt(mock)})
26 | assert.NoError(t, err)
27 | policy, err := GetPolicy(PolicyGetCtx{Ctx: ctx, Name: "global-alb2", Ns: "cpaas-system", Drv: drv, L: l})
28 | assert.NoError(t, err)
29 | _ = policy
30 | _ = lu.PrettyJson(policy)
31 | l.Info("p", "p", lu.PrettyJson(policy))
32 | }
33 |
--------------------------------------------------------------------------------
/cmd/utils/albctl/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "alauda.io/alb2/cmd/utils/albctl/cmd"
4 |
5 | func main() {
6 | cmd.Execute()
7 | }
8 |
--------------------------------------------------------------------------------
/cmd/utils/dirhash/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 |
7 | "alauda.io/alb2/utils/dirhash"
8 | )
9 |
10 | func main() {
11 | out, err := dirhash.HashDir(os.Args[1], "", dirhash.DefaultHash)
12 | if err != nil {
13 | panic(err)
14 | }
15 | fmt.Printf("%s\n", out)
16 | }
17 |
--------------------------------------------------------------------------------
/cmd/utils/ngx_gen/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "os"
7 | "strings"
8 |
9 | . "alauda.io/alb2/pkg/controller/ngxconf"
10 | )
11 |
12 | func main() {
13 | ngx_raw, err := io.ReadAll(os.Stdin)
14 | if err != nil {
15 | panic(err)
16 | }
17 | ngx, err := NgxTmplCfgFromYaml(string(ngx_raw))
18 | if err != nil {
19 | panic(err)
20 | }
21 |
22 | out, err := RenderNginxConfigEmbed(*ngx)
23 | if err != nil {
24 | panic(err)
25 | }
26 | fmt.Print(strings.TrimSpace(out))
27 | }
28 |
--------------------------------------------------------------------------------
/cmd/utils/sync_rbac/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {
4 | // 1. alb cluster come from alb-clusterrole.json
5 | // 2. alb-operator clusterrole come from resource/rbac/alb-operator-clusterrole.yaml
6 | // this tools will update operator clusterrole in chart's operator-clusterrole.yaml and deploy-csv.yaml
7 | }
8 |
--------------------------------------------------------------------------------
/cmd/utils/tweak_gen/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "path"
7 |
8 | "alauda.io/alb2/pkg/operator/controllers/depl/resources/configmap"
9 | )
10 |
11 | // generate configmap used for nginx test
12 | func main() {
13 | outDir := os.Args[1]
14 | err := os.MkdirAll(outDir, 0o700)
15 | if err != nil {
16 | panic(err)
17 | }
18 | fmt.Printf("%v", configmap.HTTP)
19 | fmt.Printf("%v", outDir)
20 | toFile(configmap.HTTP, path.Join(outDir, "http.conf"))
21 | toFile(configmap.HTTPSERVER, path.Join(outDir, "http_server.conf"))
22 | toFile(configmap.UPSTREAM, path.Join(outDir, "upstream.conf"))
23 | toFile(configmap.STREAM_COMMON, path.Join(outDir, "stream-common.conf"))
24 | toFile(configmap.STREAM_TCP, path.Join(outDir, "stream-tcp.conf"))
25 | toFile(configmap.STREAM_UDP, path.Join(outDir, "stream-udp.conf"))
26 | toFile(configmap.GRPCSERVER, path.Join(outDir, "grpc_server.conf"))
27 | }
28 |
29 | func toFile(content string, path string) {
30 | f, err := os.Create(path)
31 | if err != nil {
32 | panic(err)
33 | }
34 | defer f.Close()
35 | _, err = f.WriteString(content)
36 | if err != nil {
37 | panic(err)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/config/config_ext.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "sigs.k8s.io/controller-runtime/pkg/client"
4 |
5 | func GetAlbKey(c *Config) client.ObjectKey {
6 | return client.ObjectKey{
7 | Namespace: c.GetNs(),
8 | Name: c.GetAlbName(),
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/config/mock_config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "time"
5 |
6 | . "alauda.io/alb2/pkg/config"
7 | )
8 |
9 | // type MockConfig ALBRunConfig
10 |
11 | func Mock(name, ns string) *Config {
12 | mock := DefaultMock()
13 | mock.ALBRunConfig.Name = name
14 | mock.ALBRunConfig.Ns = ns
15 | return mock
16 | }
17 |
18 | func DefaultMock() *Config {
19 | return &Config{
20 | ALBRunConfig: ALBRunConfig{
21 | Name: "alb-dev",
22 | Ns: "cpaas-system",
23 | Domain: "cpaas.io",
24 | Controller: ControllerConfig{
25 | HttpPort: 80,
26 | HttpsPort: 443,
27 | NetworkMode: "host",
28 | MetricsPort: 1936,
29 | BackLog: 100,
30 | Flags: ControllerFlags{
31 | EnableIPV6: true,
32 | },
33 | },
34 | Gateway: GatewayConfig{},
35 | },
36 | ExtraConfig: ExtraConfig{
37 | Leader: LeaderConfig{
38 | LeaseDuration: time.Second * time.Duration(120),
39 | RenewDeadline: time.Second * time.Duration(40),
40 | RetryPeriod: time.Second * time.Duration(12),
41 | SkipExit: true,
42 | },
43 | },
44 | Names: NewNames("cpaas.io"),
45 | }
46 | }
47 |
48 | func UseMock(cfg *Config) {
49 | if cfg == nil {
50 | cfg = DefaultMock()
51 | }
52 | InTestSetConfig(*cfg)
53 | }
54 |
--------------------------------------------------------------------------------
/config/types.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | type Mode string
4 |
5 | var ModeKey = "MODE"
6 |
7 | const (
8 | Controller Mode = "controller"
9 | Operator Mode = "operator"
10 | )
11 |
12 | type ControllerNetWorkMode string
13 |
14 | var NetworkModeKey = "NETWORK_MODE"
15 |
16 | const (
17 | Host ControllerNetWorkMode = "host"
18 | Container ControllerNetWorkMode = "container"
19 | )
20 |
21 | type NginxCfg struct {
22 | NginxTemplatePath string
23 | NewConfigPath string
24 | OldConfigPath string
25 | NewPolicyPath string
26 | EnablePrometheus bool
27 | EnableHttp2 bool
28 | EnableGzip bool
29 | BackLog int
30 | EnableIpv6 bool
31 | TweakDir string
32 | }
33 |
--------------------------------------------------------------------------------
/controller/cli/cert_test.go:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | "sigs.k8s.io/controller-runtime/pkg/client"
8 | )
9 |
10 | func TestCert(t *testing.T) {
11 | assert.Equal(t,
12 | formatCertsMap(map[string]map[string][]client.ObjectKey{
13 | "80": {
14 | "a.com": {
15 | {Namespace: "a", Name: "a2"},
16 | {Namespace: "a", Name: "a1"},
17 | {Namespace: "a", Name: "a3"},
18 | },
19 | },
20 | "90": {
21 | "b.com": {
22 | {Namespace: "a", Name: "b1"},
23 | },
24 | "c.com": {
25 | {Namespace: "a", Name: "c1"},
26 | },
27 | },
28 | "91": {
29 | "b.com": {
30 | {Namespace: "a", Name: "b2"},
31 | },
32 | },
33 | }),
34 | map[string]client.ObjectKey{
35 | "a.com": {Namespace: "a", Name: "a1"},
36 | "b.com/90": {Namespace: "a", Name: "b1"},
37 | "b.com/91": {Namespace: "a", Name: "b2"},
38 | "c.com": {Namespace: "a", Name: "c1"},
39 | },
40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/controller/cli/policy_l4.go:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import (
4 | . "alauda.io/alb2/controller/types"
5 | albv1 "alauda.io/alb2/pkg/apis/alauda/v1"
6 | )
7 |
8 | func (p *PolicyCli) initStreamModeFt(ft *Frontend, ngxPolicy *NgxPolicy) {
9 | // create a default rule for stream mode ft.
10 | policy := Policy{}
11 | policy.Source = Source{}
12 | policy.Subsystem = SubsystemStream
13 | // @ft_default_policy
14 | upstream, rule := getName(ft)
15 | policy.Upstream = upstream
16 | policy.Rule = rule
17 | p.cus.InitL4DefaultPolicy(ft, &policy)
18 |
19 | if ft.Protocol == albv1.FtProtocolTCP {
20 | ngxPolicy.Stream.Tcp[ft.Port] = append(ngxPolicy.Stream.Tcp[ft.Port], &policy)
21 | }
22 | if ft.Protocol == albv1.FtProtocolUDP {
23 | ngxPolicy.Stream.Udp[ft.Port] = append(ngxPolicy.Stream.Udp[ft.Port], &policy)
24 | }
25 | }
26 |
27 | // gateway-api中就是ft没有默认backend-group 但是有rule
28 | func getName(ft *Frontend) (upstream string, rule string) {
29 | if len(ft.Rules) > 0 {
30 | rule := ft.Rules[0]
31 | if rule.BackendGroup != nil {
32 | return rule.BackendGroup.Name, rule.RuleID
33 | }
34 | // 可能是redirect规则。用rule id即可。在没有backend-group的情况下,upstream name 是什么都行
35 | return rule.RuleID, rule.RuleID
36 | }
37 | if ft.BackendGroup != nil {
38 | return ft.BackendGroup.Name, ft.BackendGroup.Name
39 | }
40 | return "", ""
41 | }
42 |
--------------------------------------------------------------------------------
/controller/modules/consts.go:
--------------------------------------------------------------------------------
1 | package modules
2 |
3 | import alb2v1 "alauda.io/alb2/pkg/apis/alauda/v1"
4 |
5 | const (
6 | // ProtoHTTP is the protocol of http frontend
7 | ProtoHTTP = alb2v1.FtProtocolHTTP
8 | ProtoHTTPS = alb2v1.FtProtocolHTTPS
9 | )
10 |
11 | // source type
12 | const (
13 | TypeIngress = "ingress"
14 | TypeFtDefaultRouter = "ft_default_router"
15 | TypeExtension = "extension"
16 | TypeHttpRoute = "httpRoute"
17 | TypeTCPRoute = "tcpRoute"
18 | TypeUDPRoute = "udpRoute"
19 | )
20 |
21 | const (
22 | ProjectALL = "ALL_ALL"
23 | )
24 |
25 | type AlbPhase string
26 |
27 | const (
28 | PhaseStarting AlbPhase = "starting"
29 | PhaseRunning AlbPhase = "running"
30 | PhaseTerminating AlbPhase = "terminating"
31 | )
32 |
--------------------------------------------------------------------------------
/controller/state/state.go:
--------------------------------------------------------------------------------
1 | package state
2 |
3 | import (
4 | "sync"
5 |
6 | . "alauda.io/alb2/controller/modules"
7 | )
8 |
9 | // 维护一些全局的alb的状态 目前只有优雅退出的特性用到了
10 |
11 | type State struct {
12 | phase AlbPhase
13 | lock sync.Mutex
14 | }
15 |
16 | var (
17 | instance *State
18 | once sync.Once
19 | )
20 |
21 | func GetState() *State {
22 | once.Do(func() {
23 | instance = &State{
24 | phase: PhaseStarting,
25 | lock: sync.Mutex{},
26 | }
27 | })
28 | return instance
29 | }
30 |
31 | func (s *State) GetPhase() AlbPhase {
32 | s.lock.Lock()
33 | defer s.lock.Unlock()
34 | return s.phase
35 | }
36 |
37 | func (s *State) SetPhase(p AlbPhase) {
38 | s.lock.Lock()
39 | defer s.lock.Unlock()
40 | s.phase = p
41 | }
42 |
--------------------------------------------------------------------------------
/controller/types/consts.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | const (
4 | SubsystemHTTP = "http"
5 | SubsystemStream = "stream"
6 |
7 | PolicySIPHash = "sip-hash"
8 | PolicyCookie = "cookie"
9 |
10 | CaCert = "ca.crt"
11 | )
12 |
13 | var (
14 | LastConfig = ""
15 | LastFailure = false
16 | )
17 |
18 | const (
19 | ModeTCP = "tcp"
20 | ModeHTTP = "http"
21 | ModeUDP = "udp"
22 | ModegRPC = "grpc"
23 | )
24 |
25 | const (
26 | RuleTypeIngress = "ingress"
27 | RuleTypeGateway = "gateway"
28 | )
29 |
--------------------------------------------------------------------------------
/controller/types/policyext_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "encoding/json"
5 | "strings"
6 | "testing"
7 |
8 | otelt "alauda.io/alb2/pkg/controller/ext/otel/types"
9 | lu "alauda.io/alb2/utils"
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | func TestJson(t *testing.T) {
14 | p := Policy{}
15 | p_json := lu.PrettyJson(p)
16 | t.Log()
17 | assert.Equal(t, !strings.Contains(p_json, "null"), true)
18 | }
19 |
20 | func TestToMaps(t *testing.T) {
21 | p := PolicyExtCfg{
22 | PolicyExt: PolicyExt{
23 | Otel: &otelt.OtelConf{
24 | Exporter: &otelt.Exporter{},
25 | },
26 | RewriteResponse: &RewriteResponseConfig{},
27 | },
28 | }
29 | m := p.ToMaps()
30 | js, err := json.MarshalIndent(m, " ", " ")
31 | assert.NoError(t, err)
32 | t.Logf("m %s", string(js))
33 | assert.Equal(t, 2, len(m))
34 | }
35 |
36 | func TestClean(t *testing.T) {
37 | p := PolicyExt{
38 | Otel: &otelt.OtelConf{
39 | Exporter: &otelt.Exporter{},
40 | },
41 | RewriteResponse: &RewriteResponseConfig{},
42 | }
43 | p.Clean("otel")
44 | }
45 |
--------------------------------------------------------------------------------
/deploy/README.md:
--------------------------------------------------------------------------------
1 | ## csv and rbac
2 | 现在csv是直接在chart中部署的
3 | 因为发现这种方式无法创建出serviceaccount,所以rbac相关的资源是chart直接创建的
4 | ## gatewayapi
5 | | gatewayapi v0.6.2 | v1alpha2 | v1beta1 | v1 |
6 | |-------------------|------------|------------|----|
7 | | gatewayclass | v | v(storage) | |
8 | | gateway | v | v(storage) | |
9 | | httproute | v | v(storage) | |
10 | | tcproute | v(storage) | | |
11 | | udproute | v(storage) | | |
12 | | tlsroute | v(storage) | | |
13 | | referencegrant | v(storage) | v |
14 | | grpcroute | v(storage) | | |
15 | |-------------------|------------|------------|----|
16 |
17 | | gatewayapi v1.0.0 | v1alpha2 | v1beta1 | v1 |
18 | |-------------------|------------|------------|----|
19 | | gatewayclass | | v(storage) | v |
20 | | gatway | | v(storage) | v |
21 | | httproute | | v(storage) | v |
22 | | tcproute | v(storage) | | |
23 | | udproute | v(storage) | | |
24 | | tlsroute | v(storage) | | |
25 | | referencegrant | v | v(storage) | |
26 | | grpcroute | v(storage) | | |
27 | | btlspolicy | v(storage) | | |
--------------------------------------------------------------------------------
/deploy/chart/alb/Chart.yaml:
--------------------------------------------------------------------------------
1 | name: alauda-alb2
2 | version: v3.19.0-beta.22.gad8523c5
3 | description: alauda loadbalancer version 2
4 | apiVersion: v2
5 | annotations:
6 | release: alpha
7 | branch: master
8 | commit: ad8523c5953f8a579f1cbc17774ef70fb399183a
9 |
--------------------------------------------------------------------------------
/deploy/chart/alb/templates/alb.featuregate.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Capabilities.APIVersions.Has "ait.alauda.io/v1alpha2" -}}
2 | {{ $publicCloudProvider := .Values.global.publicCloudProvider }}
3 | {{ $clusterType := .Values.global.cluster.type }}
4 | {{ if has $clusterType $publicCloudProvider }}
5 | apiVersion: alauda.io/v1
6 | kind: ClusterAlaudaFeatureGate
7 | metadata:
8 | name: alb2
9 | namespace: '{{.Values.global.namespace}}'
10 | spec:
11 | description: "增强型负载均衡,为应用提供丰富功能的负载均衡策略和配置,集群级功能开关添加于 v3.12"
12 | enabled: true
13 | stage: GA
14 | {{ end }}
15 | {{- end }}
--------------------------------------------------------------------------------
/deploy/chart/alb/templates/alb.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.defaultAlb }}
2 | {{- $global := .Values.global }}
3 | {{- $value_copy := deepCopy .Values }}
4 | {{- $value_without_global := unset $value_copy "global" }}
5 | {{- $value_without_console := unset $value_without_global "alaudaConsole" }}
6 | {{- $value_clean := $value_without_console }}
7 | {{- $cfg := $value_clean }}
8 | {{ $fullProjects := .Values.projects | uniq }}
9 | apiVersion: crd.alauda.io/v2beta1
10 | kind: ALB2
11 | metadata:
12 | name: {{ .Values.loadbalancerName }}
13 | namespace: {{ $global.namespace }}
14 | labels:
15 | alb.{{ $global.labelBaseDomain}}/managed-by: alb-operator
16 | alb.{{ $global.labelBaseDomain}}/migrate-from: sentry
17 | alb.{{ $global.labelBaseDomain}}/deploy-by: sentry
18 | alb.{{ $global.labelBaseDomain}}/default-alb: "true"
19 | {{- range $fullProjects }}
20 | {{ if . }}
21 | project.{{ $global.labelBaseDomain }}/{{ . }}: "true"
22 | {{ end}}
23 | {{- end}}
24 | annotations:
25 | {{ $global.labelBaseDomain }}/display-name: {{ .Values.displayName |quote }}
26 | helm.sh/waitResources: "[{\"apiVersion\": \"apps/v1\", \"kind\": \"Deployment\", \"namespace\": \"{{ .Release.Namespace }}\", \"name\": \"{{ .Values.loadbalancerName }}\"}]"
27 | alb.{{ $global.labelBaseDomain }}/migrate-backup: |
28 | {{ $cfg | toJson }}
29 | update-mode: put
30 | spec:
31 | address: {{ .Values.address | quote }}
32 | type: "nginx"
33 | config:
34 | {{ $cfg | toYaml | indent 4 }}
35 | {{- end }}
--------------------------------------------------------------------------------
/deploy/chart/alb/templates/loadbalancer-service.featuregate.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Capabilities.APIVersions.Has "ait.alauda.io/v1alpha2" -}}
2 | apiVersion: alauda.io/v1
3 | kind: ClusterAlaudaFeatureGate
4 | metadata:
5 | name: loadbalancer-service
6 | namespace: '{{.Values.global.namespace}}'
7 | spec:
8 | description: "LoadBalancer类型Service,添加于v3.10"
9 | enabled: true
10 | stage: GA
11 | {{- end }}
12 |
--------------------------------------------------------------------------------
/deploy/chart/alb/templates/operator-clusterrolebinding.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: rbac.authorization.k8s.io/v1
2 | kind: ClusterRoleBinding
3 | metadata:
4 | name: alb-operator
5 | roleRef:
6 | apiGroup: rbac.authorization.k8s.io
7 | kind: ClusterRole
8 | name: alb-operator
9 | subjects:
10 | - kind: ServiceAccount
11 | name: alb-operator
12 | namespace: {{.Values.global.namespace}}
--------------------------------------------------------------------------------
/deploy/chart/alb/templates/operator-sa.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | imagePullSecrets:
4 | {{- range $_, $v := .Values.global.registry.imagePullSecrets }}
5 | - name: {{ $v }}
6 | {{- end }}
7 | metadata:
8 | name: alb-operator
9 | namespace: {{.Values.global.namespace}}
10 |
--------------------------------------------------------------------------------
/deploy/chart/alb/values.yaml:
--------------------------------------------------------------------------------
1 | ## global
2 | operator:
3 | albImagePullPolicy: Always
4 | defaultAlb: true # 部署默认的alb
5 | operatorReplicas: 1
6 | operatorDeployMode: "deployment"
7 | displayName: ""
8 | address: 127.0.0.1 # address of the default alb
9 | projects: []
10 | global:
11 | platformscenario: base
12 | labelBaseDomain: cpaas.io
13 | namespace: cpaas-system
14 | registry:
15 | address: registry.alauda.cn:60080
16 | images:
17 | alb2:
18 | code: gitlab-ce.alauda.cn/container-platform/alb2
19 | support_arm: true
20 | repository: acp/alb2
21 | tag: v3.19.0-beta.22.gad8523c5
22 | nginx:
23 | code: gitlab-ce.alauda.cn/container-platform/alb2
24 | support_arm: true
25 | repository: acp/alb-nginx
26 | tag: "v3.19.0-beta.22.gad8523c5"
27 | resources:
28 | alb:
29 | limits:
30 | cpu: "200m"
31 | memory: 2Gi
32 | requests:
33 | cpu: 50m
34 | memory: 128Mi
35 | limits:
36 | cpu: "2"
37 | memory: 2Gi
38 | requests:
39 | cpu: 50m
40 | memory: 128Mi
41 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | [[release-note/README|release-note]]
2 | ## features
3 | [[rules]]
4 | [[api-containermode-gateway-deploy]]
5 | [[api-ingressclass]]
6 | [[rules]]
7 | [[errorpage]]
8 | [[feature/otel/otel]]
9 | [[modsecurity.en]]
10 | [[auth]]
--------------------------------------------------------------------------------
/docs/_res/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/docs/_res/architecture.png
--------------------------------------------------------------------------------
/docs/feature/auth/dev_readme.md:
--------------------------------------------------------------------------------
1 | # ALB Auth 实现说明
2 |
3 | ALB 在实现 auth 相关 annotation 时采用了不同于 ingress-nginx 的实现方式:
4 |
5 | - ingress-nginx 是基于模板修改 nginx.conf 实现
6 | - ALB 是基于 OpenResty 的 Lua 实现
7 |
8 | 这种实现方式带来以下优势:
9 | 1. 支持更复杂的认证功能
10 | 2. 认证配置变更时无需重载 nginx
11 |
12 | 虽然实现方式不同,但 ALB 会保持与 ingress-nginx 的行为一致性:
13 | - 相同的 annotation 在 ingress-nginx 和 ALB 上效果一致,无需改动.
14 |
15 | 为了保证行为一致性,我们使用 ./test/conformance/ingress-nginx 中的测试用例来验证。这套测试用例可以同时在 ingress-nginx 和 ALB 上运行,确保功能的一致性。
16 |
17 | # 代码
18 | go 部分代码在 ./pkg/controller/ext/auth/auth.go
19 | lua 部分代码在 ./template/nginx/lua/plugins/auth/auth.lua
--------------------------------------------------------------------------------
/docs/feature/errorpage/errorpage.md:
--------------------------------------------------------------------------------
1 | ## Error Page
2 | ### 概述
3 | 我们不希望用户能看到openresty这种体现技术栈的字样。
4 | 1. 当应用返回错误时, alb返回的body和应用返回的body一致。
5 | 1. 没有body时,alb也不会返回body
6 | 2. 当alb自身返回错误时, alb返回的body为
7 | ```
8 | X-Error: $status
9 | ```
10 | ### 例外
11 | 当开启了 [[modsecurity]] 之后,如果因为waf规则返回了错误码,返回的body为
12 | ```
13 |
14 |
15 | 403 Forbidden
16 |
17 |
18 |
19 | 403 Forbidden
20 |
21 |
22 | openresty
23 |
24 |
25 | ```
26 |
--------------------------------------------------------------------------------
/docs/feature/otel/_res/jaeger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/docs/feature/otel/_res/jaeger.png
--------------------------------------------------------------------------------
/docs/feature/otel/_res/trace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/docs/feature/otel/_res/trace.png
--------------------------------------------------------------------------------
/docs/release-note/README.md:
--------------------------------------------------------------------------------
1 | # ACP v3.18
2 | ## ACP v3.18.1
3 | state: RELEASE
4 | chart: v3.18.2
5 | image: v3.18.2
6 | ### change
7 | #### feature
8 | * add support of [[otel]] [otel](https://github.com/alauda/alb/commit/16ee00dd009cda1bd5fb48ad803b48fe5427d2b6)
9 | * add cpaas.io/project label in ingress synced rule.
10 | * add support of [[modsecurity]]
11 | #### other
12 | * tweak github ci. we could build and test in github now
13 | * deploy alb-operator via deployment. do not use csv anymore
14 | * add MonitorDashboard in chart
15 | * https and authed metrics
16 | * add source name/ns label in rule. (first 63 chars if name/ns is longer than 63)
17 | * api: filter project when list rules
18 | * unquote cookie value when rewrite request header via var
19 | * swap policy
20 | * fix CORS when has multi-domain
21 | * donot use placeholder crt/key
--------------------------------------------------------------------------------
/driver/constants.go:
--------------------------------------------------------------------------------
1 | package driver
2 |
3 | const (
4 | OwnerUnknown = "Unknown"
5 | )
6 |
--------------------------------------------------------------------------------
/gateway/constant.go:
--------------------------------------------------------------------------------
1 | package gateway
2 |
3 | import (
4 | sets "github.com/deckarep/golang-set/v2"
5 | )
6 |
7 | // log tag
8 | const (
9 | ALB_GATEWAY_CONTROLLER = "agctl" // gateway/xxroute controller relevant. a(lb)g(ateway)c(on)t(rol)l(er)
10 | ALB_GATEWAY_NGINX = "agng" // nginx config relevant. a(lb)g(ateway)ng(inxconfiggenerater)
11 | )
12 |
13 | const (
14 | GATEWAY_GROUP = "gateway.networking.k8s.io"
15 | GATEWAY_KIND = "Gateway"
16 | )
17 |
18 | const (
19 | GatewayClassKind = "GatewayClass"
20 | GatewayKind = "Gateway"
21 | HttpRouteKind = "HTTPRoute"
22 | TcpRouteKind = "TCPRoute"
23 | UdpRouteKind = "UDPRoute"
24 | )
25 |
26 | var SUPPORT_KIND_MAP map[string][]string = map[string][]string{
27 | "TCP": {TcpRouteKind},
28 | "UDP": {UdpRouteKind},
29 | "HTTP": {HttpRouteKind},
30 | "HTTPS": {HttpRouteKind},
31 | }
32 |
33 | var SUPPORT_KIND_SET sets.Set[string] = sets.NewSet(TcpRouteKind, UdpRouteKind, HttpRouteKind)
34 |
--------------------------------------------------------------------------------
/gateway/ctl/constants.go:
--------------------------------------------------------------------------------
1 | package ctl
2 |
3 | type CommonRouteConditionReason string
4 |
5 | const (
6 | CommonRouteReasonInvalidSectionName CommonRouteConditionReason = "InvalidSectionName"
7 | CommonRouteReasonUnAllowRoute CommonRouteConditionReason = "UnAllowRoute"
8 | CommonRouteReasonInvalidKind CommonRouteConditionReason = "InvalidKind"
9 | )
10 |
--------------------------------------------------------------------------------
/gateway/ctl/hostname_filter.go:
--------------------------------------------------------------------------------
1 | package ctl
2 |
3 | import (
4 | . "alauda.io/alb2/gateway"
5 | . "alauda.io/alb2/gateway/utils"
6 | "github.com/go-logr/logr"
7 | "github.com/samber/lo"
8 | gv1 "sigs.k8s.io/gateway-api/apis/v1"
9 | )
10 |
11 | type HostNameFilter struct {
12 | log logr.Logger
13 | }
14 |
15 | func (c *HostNameFilter) Name() string {
16 | return "HostNameFilter"
17 | }
18 |
19 | func (c *HostNameFilter) FilteRoute(ref gv1.ParentReference, r *Route, ls *Listener) bool {
20 | // allow routes
21 | lsHost := ls.Hostname
22 | if lsHost == nil {
23 | return true
24 | }
25 |
26 | h, ok := r.route.(*HTTPRoute)
27 | // only focus on http route.
28 | if !ok {
29 | return true
30 | }
31 |
32 | routeHost := lo.Map(h.Spec.Hostnames, func(s gv1.Hostname, _ int) string { return string(s) })
33 |
34 | domains := FindIntersection(string(*lsHost), routeHost)
35 | if len(domains) == 0 {
36 | r.unAllowRoute(ref, "no intersection hostname")
37 | return false
38 | }
39 | return true
40 | }
41 |
--------------------------------------------------------------------------------
/gateway/ctl/hostname_filter_test.go:
--------------------------------------------------------------------------------
1 | package ctl
2 |
3 | import (
4 | "testing"
5 |
6 | "alauda.io/alb2/gateway/utils"
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestHostNameFilter(t *testing.T) {
11 | type TestCase struct {
12 | host string
13 | route []string
14 | result []string
15 | }
16 | cases := []TestCase{
17 | {
18 | host: "a.com",
19 | route: []string{"a.com"},
20 | result: []string{"a.com"},
21 | },
22 | {
23 | host: "a.com",
24 | route: []string{},
25 | result: []string{"a.com"},
26 | },
27 | {
28 | host: "*.a.com",
29 | route: []string{"a.com"},
30 | result: []string{},
31 | },
32 | {
33 | host: "*.a.com",
34 | route: []string{},
35 | result: []string{"*.a.com"},
36 | },
37 | {
38 | host: "*.a.com",
39 | route: []string{"a.a.com", "b.a.com"},
40 | result: []string{"a.a.com", "b.a.com"},
41 | },
42 | {
43 | host: "b.a.com",
44 | route: []string{"*.a.com", "b.a.com", "a.a.com"},
45 | result: []string{"*.a.com", "b.a.com"},
46 | },
47 | }
48 | for _, test := range cases {
49 | result := utils.FindIntersection(test.host, test.route)
50 | assert.Equal(t, test.result, result)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/gateway/ctl/reservedPortFilter.go:
--------------------------------------------------------------------------------
1 | package ctl
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/go-logr/logr"
7 | gv1b1t "sigs.k8s.io/gateway-api/apis/v1"
8 | )
9 |
10 | const RouteNotReadyReasonReservedPort = "ReservedPortUsed"
11 |
12 | type ReservedPortFilter struct {
13 | log logr.Logger
14 | reservedPorts map[int]bool
15 | }
16 |
17 | func NewReservedPortFilter(log logr.Logger, ports []int) ReservedPortFilter {
18 | m := map[int]bool{}
19 | for _, p := range ports {
20 | m[p] = true
21 | }
22 | log.Info("reservedPorts", "ports", m)
23 | return ReservedPortFilter{
24 | log: log,
25 | reservedPorts: m,
26 | }
27 | }
28 |
29 | func (c *ReservedPortFilter) Name() string {
30 | return "ReservedPortFilter"
31 | }
32 |
33 | func (c *ReservedPortFilter) FilteRoute(ref gv1b1t.ParentReference, r *Route, ls *Listener) bool {
34 | if c.reservedPorts[int(ls.Port)] {
35 | r.unAllowRouteWithReason(ref, fmt.Sprintf("%v is our reserved port", c.reservedPorts), RouteNotReadyReasonReservedPort)
36 | return false
37 | }
38 | return true
39 | }
40 |
--------------------------------------------------------------------------------
/gateway/nginx/policyattachment/manager.go:
--------------------------------------------------------------------------------
1 | package policyattachment
2 |
3 | import (
4 | "context"
5 |
6 | . "alauda.io/alb2/controller/types"
7 | "alauda.io/alb2/driver"
8 | . "alauda.io/alb2/gateway/nginx/policyattachment/types"
9 | "github.com/go-logr/logr"
10 | )
11 |
12 | type PolicyAttachmentManager struct {
13 | ctx context.Context
14 | log logr.Logger
15 | drv *driver.KubernetesDriver
16 | timeout TimeoutPolicy
17 | }
18 |
19 | // manager of all policyattachment, recreate when re-render config.
20 | func NewPolicyAttachmentManager(ctx context.Context, drv *driver.KubernetesDriver, log logr.Logger) (*PolicyAttachmentManager, error) {
21 | timeout, err := NewTimeoutPolicy(ctx, log.WithName("timeout"), drv)
22 | if err != nil {
23 | return nil, err
24 | }
25 | return &PolicyAttachmentManager{
26 | ctx: ctx,
27 | log: log,
28 | drv: drv,
29 | timeout: *timeout,
30 | }, nil
31 | }
32 |
33 | func (pm *PolicyAttachmentManager) OnRule(ft *Frontend, rule *InternalRule, ref Ref) error {
34 | // TODO 当一个policyattachment出错时,应该如何处理?
35 | err := pm.timeout.OnRule(ft, rule, ref)
36 | if err != nil {
37 | return err
38 | }
39 | return nil
40 | }
41 |
--------------------------------------------------------------------------------
/gateway/nginx/policyattachment/timeout_policy_test.go:
--------------------------------------------------------------------------------
1 | package policyattachment
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 |
7 | gatewayPolicy "alauda.io/alb2/pkg/apis/alauda/gateway/v1alpha1"
8 | "github.com/openlyinc/pointy"
9 | "github.com/stretchr/testify/assert"
10 | )
11 |
12 | func TestIPolicyAttachmentConfig(t *testing.T) {
13 | timeout := gatewayPolicy.TimeoutPolicyConfig{
14 | ProxyConnectTimeoutMs: nil,
15 | ProxyReadTimeoutMs: pointy.Uint(10),
16 | }
17 | timeoutJson, err := json.Marshal(timeout)
18 | assert.Equal(t, string(timeoutJson), `{"proxy_read_timeout_ms":10}`)
19 | assert.NoError(t, err)
20 | t.Logf("%s", timeoutJson)
21 | timeout1 := TimeoutPolicyConfig(timeout)
22 | ret := TimeoutPolicyConfig{}
23 | ret.FromConfig(timeout1.IntoConfig())
24 | assert.Nil(t, ret.ProxyConnectTimeoutMs)
25 | assert.Equal(t, *ret.ProxyReadTimeoutMs, uint(10))
26 | assert.Nil(t, ret.ProxySendTimeoutMs)
27 | }
28 |
--------------------------------------------------------------------------------
/gateway/nginx/types/types.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "fmt"
5 | "time"
6 |
7 | pmType "alauda.io/alb2/gateway/nginx/policyattachment/types"
8 | albv1 "alauda.io/alb2/pkg/apis/alauda/v1"
9 | "sigs.k8s.io/controller-runtime/pkg/client"
10 | gatewayType "sigs.k8s.io/gateway-api/apis/v1"
11 |
12 | "alauda.io/alb2/controller/types"
13 | "alauda.io/alb2/gateway"
14 | )
15 |
16 | type Listener struct {
17 | gatewayType.Listener
18 | Gateway client.ObjectKey
19 | Generation int64
20 | CreateTime time.Time
21 | Routes []gateway.CommonRoute
22 | }
23 |
24 | type FtMap map[string]*types.Frontend
25 |
26 | func (f FtMap) SetFt(protocol string, port albv1.PortNumber, ft *types.Frontend) {
27 | key := fmt.Sprintf("%v:%v", protocol, port)
28 | f[key] = ft
29 | }
30 |
31 | type GatewayAlbTranslate interface {
32 | TransLate(ls []*Listener, ftMap FtMap) error
33 | }
34 |
35 | // who implement this interface have responsibility to call OnRule when a rule been create.
36 | type GatewayAlbPolicyAttachment interface {
37 | SetPolicyAttachmentHandle(handle pmType.PolicyAttachmentHandle)
38 | }
39 |
--------------------------------------------------------------------------------
/gateway/nginx/utils/utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 |
6 | "alauda.io/alb2/utils"
7 | gatewayType "sigs.k8s.io/gateway-api/apis/v1"
8 |
9 | . "alauda.io/alb2/controller/types"
10 | )
11 |
12 | // translate gateway matchType.to alb op
13 | // Exact => EQ
14 | // PathPrefix => STARTS_WITH
15 | // RegularExpression => REGEX
16 | // nil => EQ
17 | // otherwise return err
18 | func ToOP(matchType *string) (string, error) {
19 | if matchType == nil {
20 | return utils.OP_EQ, nil
21 | }
22 | switch *matchType {
23 | case "Exact":
24 | return utils.OP_EQ, nil
25 | case "PathPrefix":
26 | return utils.OP_STARTS_WITH, nil
27 | case "RegularExpression":
28 | return utils.OP_REGEX, nil
29 | default:
30 | return "", fmt.Errorf("unsupported match type %v", matchType)
31 | }
32 | }
33 |
34 | func BackendRefsToService(refs []gatewayType.BackendRef) ([]*BackendService, error) {
35 | svcs := []*BackendService{}
36 | for _, ref := range refs {
37 | kind := ref.Kind
38 | if kind != nil && *kind != "Service" {
39 | return nil, fmt.Errorf("gateway: backend ref kind is not service but %v", kind)
40 | }
41 | if ref.Namespace == nil || ref.Port == nil || ref.Weight == nil {
42 | return nil, fmt.Errorf("invalid ref %v", ref)
43 | }
44 | svcs = append(svcs, &BackendService{
45 | ServiceNs: string(*ref.Namespace),
46 | ServiceName: string(ref.Name),
47 | ServicePort: int(*ref.Port),
48 | Weight: int(*ref.Weight),
49 | })
50 | }
51 | return svcs, nil
52 | }
53 |
--------------------------------------------------------------------------------
/gateway/utils/hostname.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "strings"
4 |
5 | func FindIntersection(lsHost string, routeHost []string) []string {
6 | if len(routeHost) == 0 {
7 | return []string{lsHost}
8 | }
9 | ret := []string{}
10 |
11 | for _, rh := range routeHost {
12 | if matchDomain(lsHost, rh) {
13 | ret = append(ret, rh)
14 | }
15 | }
16 | return ret
17 | }
18 |
19 | func matchDomain(host, route string) bool {
20 | hostIsWildcard := strings.HasPrefix(host, "*.")
21 | routeIsWildcard := strings.HasPrefix(route, "*.")
22 | if hostIsWildcard && !routeIsWildcard {
23 | hostWithoutWildcard := strings.TrimPrefix(host, "*")
24 | return strings.HasSuffix(route, hostWithoutWildcard)
25 | }
26 | if !hostIsWildcard && routeIsWildcard {
27 | routeWithoutWildcard := strings.TrimPrefix(route, "*")
28 | return strings.HasSuffix(host, routeWithoutWildcard)
29 | }
30 | return host == route
31 | }
32 |
--------------------------------------------------------------------------------
/ingress/project.go:
--------------------------------------------------------------------------------
1 | package ingress
2 |
3 | import (
4 | "fmt"
5 |
6 | m "alauda.io/alb2/controller/modules"
7 | "github.com/thoas/go-funk"
8 | networkingv1 "k8s.io/api/networking/v1"
9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10 | "k8s.io/apimachinery/pkg/labels"
11 | )
12 |
13 | func (c *Controller) GetProjectIngresses(projects []string) []*networkingv1.Ingress {
14 | if funk.ContainsString(projects, m.ProjectALL) {
15 | ingress, err := c.ingressLister.Ingresses("").List(labels.Everything())
16 | if err != nil {
17 | c.log.Error(err, "")
18 | return nil
19 | }
20 | return ingress
21 | }
22 | var allIngresses []*networkingv1.Ingress
23 | for _, project := range projects {
24 | sel := labels.Set{fmt.Sprintf("%s/project", c.GetDomain()): project}.AsSelector()
25 | nss, err := c.kd.Client.CoreV1().Namespaces().List(c.kd.Ctx, metav1.ListOptions{LabelSelector: sel.String()})
26 | if err != nil {
27 | c.log.Error(err, "")
28 | return nil
29 | }
30 | for _, ns := range nss.Items {
31 | ingress, err := c.ingressLister.Ingresses(ns.Name).List(labels.Everything())
32 | if err != nil {
33 | c.log.Error(err, "")
34 | return nil
35 | }
36 | allIngresses = append(allIngresses, ingress...)
37 | }
38 | }
39 | return allIngresses
40 | }
41 |
--------------------------------------------------------------------------------
/ingress/resync_test.go:
--------------------------------------------------------------------------------
1 | package ingress
2 |
3 | import (
4 | "context"
5 | "testing"
6 | "time"
7 |
8 | "k8s.io/apimachinery/pkg/util/wait"
9 | )
10 |
11 | func TestWait(t *testing.T) {
12 | ctx, cancel := context.WithCancel(context.Background())
13 | // we should wait a interval
14 | t.Logf("start %v", time.Now())
15 | go wait.UntilWithContext(ctx, func(ctx context.Context) {
16 | t.Logf("in %v", time.Now())
17 | }, time.Millisecond*100)
18 | time.Sleep(time.Second * 1)
19 | cancel()
20 | t.Logf("end %v", time.Now())
21 | time.Sleep(time.Millisecond * 500)
22 | }
23 |
--------------------------------------------------------------------------------
/ingress/util.go:
--------------------------------------------------------------------------------
1 | package ingress
2 |
3 | import (
4 | "fmt"
5 |
6 | "k8s.io/apimachinery/pkg/util/intstr"
7 | "sigs.k8s.io/controller-runtime/pkg/client"
8 |
9 | networkingv1 "k8s.io/api/networking/v1"
10 | )
11 |
12 | func HasDefaultBackend(ing *networkingv1.Ingress) bool {
13 | return len(ing.Spec.Rules) == 0 &&
14 | ing.Spec.DefaultBackend != nil &&
15 | ing.Spec.DefaultBackend.Resource == nil &&
16 | ing.Spec.DefaultBackend.Service != nil
17 | }
18 |
19 | func ToInStr(backendPort networkingv1.ServiceBackendPort) intstr.IntOrString {
20 | intStrType := intstr.Int
21 | if backendPort.Number == 0 {
22 | intStrType = intstr.String
23 | }
24 | return intstr.IntOrString{Type: intStrType, IntVal: backendPort.Number, StrVal: backendPort.Name}
25 | }
26 |
27 | type NotExistsError string
28 |
29 | // Error implements the error interface.
30 | func (e NotExistsError) Error() string {
31 | return fmt.Sprintf("no object matching key %q in local store", string(e))
32 | }
33 |
34 | func IngKey(ing *networkingv1.Ingress) client.ObjectKey {
35 | return client.ObjectKey{
36 | Namespace: ing.Namespace,
37 | Name: ing.Name,
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ingress/util/util.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import "strings"
4 |
5 | func ParseSSLAnnotation(sslAnno string) map[string]string {
6 | // alb.networking.{domain}/tls: qq.com=cpaas-system/dex.tls,qq1.com=cpaas-system/dex1.tls
7 | if sslAnno == "" {
8 | return nil
9 | }
10 | rv := make(map[string]string)
11 | parts := strings.Split(sslAnno, ",")
12 | for _, p := range parts {
13 | kv := strings.Split(strings.TrimSpace(p), "=")
14 | if len(kv) != 2 {
15 | return nil
16 | }
17 | k, v := kv[0], kv[1]
18 | if rv[k] != "" && rv[k] != v {
19 | return nil
20 | }
21 | // ["qq.com"]="cpaas-system/dex.tls"
22 | rv[k] = v
23 | }
24 | return rv
25 | }
26 |
--------------------------------------------------------------------------------
/ingress/util/util_test.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestParseSSLAnnotation(t *testing.T) {
10 | assert.Equal(t, ParseSSLAnnotation("a.com=1,a.com=1"), map[string]string{
11 | "a.com": "1",
12 | })
13 | assert.Equal(t, ParseSSLAnnotation("a.com=1,a.com=2"), (map[string]string)(nil))
14 | }
15 |
--------------------------------------------------------------------------------
/migrate/checklist/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/migrate/checklist/README.md
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.0/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header X-Real-IP $remote_addr;
5 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
6 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
7 | proxy_set_header X-Forwarded-Proto $scheme;
8 | proxy_set_header X-Forwarded-Host $http_host;
9 | proxy_set_header X-Forwarded-Port $server_port;
10 | proxy_set_header Upgrade $http_upgrade;
11 | proxy_set_header Connection $connection_upgrade;
12 |
13 | proxy_redirect off;
14 | proxy_http_version 1.1;
15 |
16 | # fix http://jira.alauda.cn/browse/SGHL-142
17 | underscores_in_headers on;
18 |
19 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.0/stream:
--------------------------------------------------------------------------------
1 | # Lua shared dict
2 | lua_code_cache on;
3 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
4 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
5 | lua_shared_dict stream_policy 10m;
6 | lua_shared_dict stream_backend_cache 5m;
7 | lua_shared_dict stream_alb_cache 20m;
8 | lua_shared_dict stream_raw 5m;
9 | lua_shared_dict stream_ipc_shared_dict 1m;
10 |
11 | proxy_connect_timeout 5s;
12 | proxy_timeout 60s;
13 | tcp_nodelay on;
14 |
15 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.0/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
3 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.10/grpc_server:
--------------------------------------------------------------------------------
1 | grpc_set_header Content-Type application/grpc;
2 | grpc_socket_keepalive on;
3 | keepalive_requests 1000;
4 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.10/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection $connection_upgrade;
6 |
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
10 | proxy_set_header X-Forwarded-Proto $scheme;
11 | proxy_set_header X-Forwarded-Host $http_host;
12 | proxy_set_header X-Forwarded-Port $server_port;
13 |
14 | proxy_set_header X-Original-URI $request_uri;
15 | proxy_set_header X-Scheme $scheme;
16 | proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
17 | proxy_set_header X-Original-Method $request_method;
18 |
19 | proxy_redirect off;
20 | proxy_http_version 1.1;
21 |
22 | # fix http://jira.alauda.cn/browse/SGHL-142
23 | underscores_in_headers on;
24 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.10/stream-common:
--------------------------------------------------------------------------------
1 | log_format stream '[$time_local] $remote_addr $protocol $server_port $status $bytes_received $bytes_sent $session_time';
2 |
3 | access_log /dev/stdout stream;
4 | error_log stderr info;
5 |
6 | lua_code_cache on;
7 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
8 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
9 |
10 | # Lua shared dict
11 | lua_shared_dict stream_policy 10m;
12 | lua_shared_dict stream_backend_cache 5m;
13 | lua_shared_dict stream_alb_cache 20m;
14 | lua_shared_dict stream_raw 5m;
15 | lua_shared_dict stream_ipc_shared_dict 1m;
16 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.10/stream-tcp:
--------------------------------------------------------------------------------
1 | proxy_next_upstream_tries 5;
2 | proxy_connect_timeout 5s;
3 | proxy_timeout 120s;
4 | tcp_nodelay on;
5 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.10/stream-udp:
--------------------------------------------------------------------------------
1 | proxy_next_upstream_tries 5;
2 | proxy_connect_timeout 5s;
3 | proxy_timeout 120s;
4 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.10/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.4/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection $connection_upgrade;
6 |
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
10 | proxy_set_header X-Forwarded-Proto $scheme;
11 | proxy_set_header X-Forwarded-Host $http_host;
12 | proxy_set_header X-Forwarded-Port $server_port;
13 |
14 | proxy_set_header X-Original-URI $request_uri;
15 | proxy_set_header X-Scheme $scheme;
16 | proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
17 | proxy_set_header X-Original-Method $request_method;
18 |
19 | proxy_redirect off;
20 | proxy_http_version 1.1;
21 |
22 | # fix http://jira.alauda.cn/browse/SGHL-142
23 | underscores_in_headers on;
24 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.4/stream:
--------------------------------------------------------------------------------
1 | # Lua shared dict
2 | lua_code_cache on;
3 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
4 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
5 | lua_shared_dict stream_policy 10m;
6 | lua_shared_dict stream_backend_cache 5m;
7 | lua_shared_dict stream_alb_cache 20m;
8 | lua_shared_dict stream_raw 5m;
9 | lua_shared_dict stream_ipc_shared_dict 1m;
10 |
11 | proxy_connect_timeout 5s;
12 | proxy_timeout 60s;
13 | tcp_nodelay on;
14 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.4/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.6.0/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection $connection_upgrade;
6 |
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
10 | proxy_set_header X-Forwarded-Proto $scheme;
11 | proxy_set_header X-Forwarded-Host $http_host;
12 | proxy_set_header X-Forwarded-Port $server_port;
13 |
14 | proxy_set_header X-Original-URI $request_uri;
15 | proxy_set_header X-Scheme $scheme;
16 | proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
17 | proxy_set_header X-Original-Method $request_method;
18 |
19 | proxy_redirect off;
20 | proxy_http_version 1.1;
21 |
22 | # fix http://jira.alauda.cn/browse/SGHL-142
23 | underscores_in_headers on;
24 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.6.0/stream:
--------------------------------------------------------------------------------
1 | # Lua shared dict
2 | lua_code_cache on;
3 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
4 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
5 | lua_shared_dict stream_policy 10m;
6 | lua_shared_dict stream_backend_cache 5m;
7 | lua_shared_dict stream_alb_cache 20m;
8 | lua_shared_dict stream_raw 5m;
9 | lua_shared_dict stream_ipc_shared_dict 1m;
10 |
11 | proxy_connect_timeout 5s;
12 | proxy_timeout 60s;
13 | tcp_nodelay on;
14 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.6.0/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.6.9/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection $connection_upgrade;
6 |
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
10 | proxy_set_header X-Forwarded-Proto $scheme;
11 | proxy_set_header X-Forwarded-Host $http_host;
12 | proxy_set_header X-Forwarded-Port $server_port;
13 |
14 | proxy_set_header X-Original-URI $request_uri;
15 | proxy_set_header X-Scheme $scheme;
16 | proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
17 | proxy_set_header X-Original-Method $request_method;
18 |
19 | proxy_redirect off;
20 | proxy_http_version 1.1;
21 |
22 | # fix http://jira.alauda.cn/browse/SGHL-142
23 | underscores_in_headers on;
24 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.6.9/stream:
--------------------------------------------------------------------------------
1 | # Lua shared dict
2 | lua_code_cache on;
3 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
4 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
5 | lua_shared_dict stream_policy 10m;
6 | lua_shared_dict stream_backend_cache 5m;
7 | lua_shared_dict stream_alb_cache 20m;
8 | lua_shared_dict stream_raw 5m;
9 | lua_shared_dict stream_ipc_shared_dict 1m;
10 | proxy_next_upstream_tries 5;
11 |
12 |
13 | proxy_connect_timeout 5s;
14 | proxy_timeout 60s;
15 | tcp_nodelay on;
16 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.6.9/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.0/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection $connection_upgrade;
6 |
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
10 | proxy_set_header X-Forwarded-Proto $scheme;
11 | proxy_set_header X-Forwarded-Host $http_host;
12 | proxy_set_header X-Forwarded-Port $server_port;
13 |
14 | proxy_set_header X-Original-URI $request_uri;
15 | proxy_set_header X-Scheme $scheme;
16 | proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
17 | proxy_set_header X-Original-Method $request_method;
18 |
19 | proxy_redirect off;
20 | proxy_http_version 1.1;
21 |
22 | # fix http://jira.alauda.cn/browse/SGHL-142
23 | underscores_in_headers on;
24 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.0/stream-common:
--------------------------------------------------------------------------------
1 | log_format stream '[$time_local] $remote_addr $protocol $server_port $status $bytes_received $bytes_sent $session_time';
2 |
3 | access_log /var/log/nginx/stream-access.log stream;
4 | error_log /var/log/nginx/stream-error.log info;
5 |
6 | lua_code_cache on;
7 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
8 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
9 |
10 | # Lua shared dict
11 | lua_shared_dict stream_policy 10m;
12 | lua_shared_dict stream_backend_cache 5m;
13 | lua_shared_dict stream_alb_cache 20m;
14 | lua_shared_dict stream_raw 5m;
15 | lua_shared_dict stream_ipc_shared_dict 1m;
16 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.0/stream-tcp:
--------------------------------------------------------------------------------
1 | proxy_next_upstream_tries 5;
2 | proxy_connect_timeout 5s;
3 | proxy_timeout 60s;
4 | tcp_nodelay on;
5 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.0/stream-udp:
--------------------------------------------------------------------------------
1 | proxy_next_upstream_tries 5;
2 | proxy_connect_timeout 5s;
3 | proxy_timeout 60s;
4 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.0/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.13/http_server:
--------------------------------------------------------------------------------
1 | # fix http://jira.alaudatech.com/browse/DEV-15515, use lua instead
2 | set $custom_host $http_host;
3 | proxy_set_header Host $custom_host;
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection $connection_upgrade;
6 |
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | # fix http://jira.alauda.cn/browse/DEVOPS-5309
10 | proxy_set_header X-Forwarded-Proto $scheme;
11 | proxy_set_header X-Forwarded-Host $http_host;
12 | proxy_set_header X-Forwarded-Port $server_port;
13 |
14 | proxy_set_header X-Original-URI $request_uri;
15 | proxy_set_header X-Scheme $scheme;
16 | proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
17 | proxy_set_header X-Original-Method $request_method;
18 |
19 | proxy_redirect off;
20 | proxy_http_version 1.1;
21 |
22 | # fix http://jira.alauda.cn/browse/SGHL-142
23 | underscores_in_headers on;
24 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.13/stream-common:
--------------------------------------------------------------------------------
1 |
2 | log_format stream '[$time_local] $remote_addr $protocol $server_port $status $bytes_received $bytes_sent $session_time';
3 |
4 | access_log /dev/stdout stream;
5 | error_log stderr info;
6 |
7 | lua_code_cache on;
8 | lua_package_path '/usr/local/lib/lua/?.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/site/lualib/?.lua;/alb/template/nginx/lua/?.lua;;';
9 | lua_package_cpath '/usr/local/lib/lua/?.so;;';
10 |
11 | # Lua shared dict
12 | lua_shared_dict stream_policy 10m;
13 | lua_shared_dict stream_backend_cache 5m;
14 | lua_shared_dict stream_alb_cache 20m;
15 | lua_shared_dict stream_raw 5m;
16 | lua_shared_dict stream_ipc_shared_dict 1m;
17 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.13/stream-tcp:
--------------------------------------------------------------------------------
1 | proxy_next_upstream_tries 5;
2 | proxy_connect_timeout 5s;
3 | proxy_timeout 120s;
4 | tcp_nodelay on;
5 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.13/stream-udp:
--------------------------------------------------------------------------------
1 | proxy_next_upstream_tries 5;
2 | proxy_connect_timeout 5s;
3 | proxy_timeout 120s;
4 |
--------------------------------------------------------------------------------
/migrate/checklist/custom/alb/check_cm/cm_map/v3.8.13/upstream:
--------------------------------------------------------------------------------
1 | keepalive 320;
2 |
--------------------------------------------------------------------------------
/migrate/checklist/helper.sh:
--------------------------------------------------------------------------------
1 | #!bin/bash
2 | ##日志函数
3 | function log::err() {
4 | printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[31mERROR: \033[0m$@\n"
5 | }
6 |
7 | function log::info() {
8 | printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[32mINFO: \033[0m$@\n"
9 | }
10 |
11 | function list_running_cluster() {
12 | kubectl get clusters.platform.tkestack.io | grep Running | awk '{print $1}'
13 | }
14 |
15 | function kubectl_with_cluster() {
16 | local CLUSTER=$1
17 | shift
18 | if [[ "$CLUSTER" = "global" ]]; then
19 | kubectl $*
20 | return
21 | fi
22 | local CLUSER_ADD=$(kubectl get clusters.platform.tkestack.io $CLUSTER -o jsonpath="{.status.addresses[0].host}")
23 | local CLUSER_PORT=$(kubectl get clusters.platform.tkestack.io $CLUSTER -o jsonpath="{.status.addresses[0].port}")
24 | local CLUSER_CC_NAME=$(kubectl get clusters.platform.tkestack.io $CLUSTER -o jsonpath="{.spec.clusterCredentialRef.name}")
25 | local CLUSTER_TOKEN=$(kubectl get cc $CLUSER_CC_NAME -oyaml | grep token | awk '{print $2}')
26 | KUBECTL="kubectl --insecure-skip-tls-verify=true --server https://$CLUSER_ADD:$CLUSER_PORT --token $CLUSTER_TOKEN"
27 | $KUBECTL $*
28 | }
29 |
--------------------------------------------------------------------------------
/migrate/checklist/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | env
3 | set -o pipefail
4 | # set -x
5 | if [[ -n "$2" ]]; then
6 | export prdb_version="$2"
7 | fi
8 | if [[ -n "$3" ]]; then
9 | export target_version="$3"
10 | fi
11 | export backup_dir="./"
12 | source helper.sh
13 | source ./custom/check-alb.sh
14 | eval "$1"
15 |
--------------------------------------------------------------------------------
/migrate/checklist/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -o pipefail
3 | source helper.sh
4 | source ./custom/check-alb.sh
5 | if [[ "$1" == "run-in-clusters" ]]; then
6 | # may read cluster from env
7 | eval "$2 global"
8 | eval "$2 p1"
9 | else
10 | eval "$@"
11 | fi
12 |
--------------------------------------------------------------------------------
/migrate/init-port-info/README.md:
--------------------------------------------------------------------------------
1 | ## 文档
2 | http://confluence.alauda.cn/pages/viewpage.action?pageId=94865661
--------------------------------------------------------------------------------
/migrate/priority/README.md:
--------------------------------------------------------------------------------
1 | # 负载均衡规则优先级迁移
2 |
3 | http://confluence.alauda.cn/pages/viewpage.action?pageId=78809412
4 |
5 | 开放rule的priority字段,范围为1-10,1最高,10最低。
6 |
7 | 历史数据迁移,历史rule用户手动创建的优先级默认为5,ingress翻译来的优先级默认为5。
8 |
9 | 需要兼容业务集群和global版本不同的情况,业务集群未升级时,规则优先级只按内部优先级生效。想使用界面配置优先级必须做升级。
--------------------------------------------------------------------------------
/migrate/v26tov28/README.md:
--------------------------------------------------------------------------------
1 | 原DSL为`(AND (OR (STARTS_WITH URL /kubernetes/) (STARTS_WITH URL /k8s/)) (EQ COOKIE test 12) (RANGE SRC_IP 1 2))`
2 |
3 | 转为json表达为
4 | ```json
5 | [
6 | {
7 | "values":[
8 | [
9 | "STARTS_WITH",
10 | "/kubernetes"
11 | ],
12 | [
13 | "STARTS_WITH",
14 | "/k8s"
15 | ]
16 | ],
17 | "type":"URL"
18 | },
19 | {
20 | "values":[
21 | [
22 | "EQ",
23 | "12"
24 | ]
25 | ],
26 | "type":"COOKIE",
27 | "key":"test"
28 | },
29 | {
30 | "values":[
31 | [
32 | "RANGE",
33 | "1",
34 | "2"
35 | ]
36 | ],
37 | "type":"SRC_IP"
38 | }
39 | ]
40 | ```
41 |
42 | 这个脚本用于更新Rule资源的dsl字段为dslx字段。由于过去dsl字段为字符串,因此部分包含了空格或者特殊符号的历史数据可能无法正确转换。需要手动删除后重新创建。
43 |
44 | 传到lua层面需要拟合的dsl结构为
45 | ```json
46 |
47 | [
48 | "AND",
49 | [
50 | "OR",
51 | [
52 | "STARTS_WITH",
53 | "URL",
54 | "/kubernetes"
55 | ],
56 | [
57 | "STARTS_WITH",
58 | "URL",
59 | "/k8s"
60 | ]
61 | ],
62 | [
63 | "EQ",
64 | "COOKIE",
65 | "test",
66 | "12"
67 | ],
68 | [
69 | "RANGE",
70 | "SRC_IP",
71 | "1",
72 | "2"
73 | ]
74 | ]
75 | ```
--------------------------------------------------------------------------------
/pkg/apis/alauda/gateway/v1alpha1/doc.go:
--------------------------------------------------------------------------------
1 | // +k8s:deepcopy-gen=package
2 |
3 | // Package v1alpha1 is the v1alpha1 version of the API.
4 | // +groupName=gateway.crd.alauda.io
5 | package v1alpha1
6 |
--------------------------------------------------------------------------------
/pkg/apis/alauda/gateway/v1alpha1/register.go:
--------------------------------------------------------------------------------
1 | package v1alpha1
2 |
3 | import (
4 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5 | "k8s.io/apimachinery/pkg/runtime"
6 | "k8s.io/apimachinery/pkg/runtime/schema"
7 | )
8 |
9 | const (
10 | GroupName = "gateway.crd.alauda.io"
11 | )
12 |
13 | // SchemeGroupVersion is group version used to register these objects
14 | var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
15 |
16 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind
17 | func Kind(kind string) schema.GroupKind {
18 | return SchemeGroupVersion.WithKind(kind).GroupKind()
19 | }
20 |
21 | // Resource takes an unqualified resource and returns a Group qualified GroupResource
22 | func Resource(resource string) schema.GroupResource {
23 | return SchemeGroupVersion.WithResource(resource).GroupResource()
24 | }
25 |
26 | var (
27 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
28 | AddToScheme = SchemeBuilder.AddToScheme
29 | )
30 |
31 | // Adds the list of known types to Scheme.
32 | func addKnownTypes(scheme *runtime.Scheme) error {
33 | scheme.AddKnownTypes(SchemeGroupVersion,
34 | &TimeoutPolicy{},
35 | &TimeoutPolicyList{},
36 | )
37 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
38 | return nil
39 | }
40 |
--------------------------------------------------------------------------------
/pkg/apis/alauda/shared/cr.go:
--------------------------------------------------------------------------------
1 | package shared
2 |
3 | import (
4 | auth_t "alauda.io/alb2/pkg/controller/ext/auth/types"
5 | otelt "alauda.io/alb2/pkg/controller/ext/otel/types"
6 | timeout_t "alauda.io/alb2/pkg/controller/ext/timeout/types"
7 | waft "alauda.io/alb2/pkg/controller/ext/waf/types"
8 | )
9 |
10 | // struct shared in alb/ft/rule
11 | // +k8s:deepcopy-gen=true
12 | type SharedCr struct {
13 | Otel *otelt.OtelCrConf `json:"otel,omitempty"`
14 | ModeSecurity *waft.WafCrConf `json:"modsecurity,omitempty"`
15 | Auth *auth_t.AuthCr `json:"auth,omitempty"`
16 | Timeout *timeout_t.TimeoutCr `json:"timeout,omitempty"`
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/apis/alauda/v1/doc.go:
--------------------------------------------------------------------------------
1 | // +k8s:deepcopy-gen=package
2 |
3 | // Package v1alpha1 is the v1alpha1 version of the API.
4 | // +groupName=crd.alauda.io
5 | package v1
6 |
--------------------------------------------------------------------------------
/pkg/apis/alauda/v1/register.go:
--------------------------------------------------------------------------------
1 | package v1
2 |
3 | import (
4 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5 | "k8s.io/apimachinery/pkg/runtime"
6 | "k8s.io/apimachinery/pkg/runtime/schema"
7 | )
8 |
9 | const (
10 | GroupName = "crd.alauda.io"
11 | )
12 |
13 | // SchemeGroupVersion is group version used to register these objects
14 | var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
15 |
16 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind
17 | func Kind(kind string) schema.GroupKind {
18 | return SchemeGroupVersion.WithKind(kind).GroupKind()
19 | }
20 |
21 | // Resource takes an unqualified resource and returns a Group qualified GroupResource
22 | func Resource(resource string) schema.GroupResource {
23 | return SchemeGroupVersion.WithResource(resource).GroupResource()
24 | }
25 |
26 | var (
27 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
28 | AddToScheme = SchemeBuilder.AddToScheme
29 | )
30 |
31 | // Adds the list of known types to Scheme.
32 | func addKnownTypes(scheme *runtime.Scheme) error {
33 | scheme.AddKnownTypes(SchemeGroupVersion,
34 | &ALB2{},
35 | &ALB2List{},
36 | &Frontend{},
37 | &FrontendList{},
38 | &Rule{},
39 | &RuleList{},
40 | )
41 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
42 | return nil
43 | }
44 |
--------------------------------------------------------------------------------
/pkg/apis/alauda/v2beta1/doc.go:
--------------------------------------------------------------------------------
1 | // +k8s:deepcopy-gen=package
2 |
3 | // Package v2beta1 is the v2beta1 version of the API.
4 | // +groupName=crd.alauda.io
5 | package v2beta1
6 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // This package has the automatically generated clientset.
20 | package versioned
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/fake/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // This package has the automatically generated fake clientset.
20 | package fake
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/scheme/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // This package contains the scheme of the automatically generated clientset.
20 | package scheme
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v1/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // This package has the automatically generated typed clients.
20 | package v1
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v1/fake/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // Package fake has the automatically generated clients.
20 | package fake
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v1/generated_expansion.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | package v1
20 |
21 | type ALB2Expansion interface{}
22 |
23 | type FrontendExpansion interface{}
24 |
25 | type RuleExpansion interface{}
26 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v2beta1/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // This package has the automatically generated typed clients.
20 | package v2beta1
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v2beta1/fake/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // Package fake has the automatically generated clients.
20 | package fake
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v2beta1/fake/fake_alauda_client.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | package fake
20 |
21 | import (
22 | v2beta1 "alauda.io/alb2/pkg/client/clientset/versioned/typed/alauda/v2beta1"
23 | rest "k8s.io/client-go/rest"
24 | testing "k8s.io/client-go/testing"
25 | )
26 |
27 | type FakeCrdV2beta1 struct {
28 | *testing.Fake
29 | }
30 |
31 | func (c *FakeCrdV2beta1) ALB2s(namespace string) v2beta1.ALB2Interface {
32 | return &FakeALB2s{c, namespace}
33 | }
34 |
35 | // RESTClient returns a RESTClient that is used to communicate
36 | // with API server by this client implementation.
37 | func (c *FakeCrdV2beta1) RESTClient() rest.Interface {
38 | var ret *rest.RESTClient
39 | return ret
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/alauda/v2beta1/generated_expansion.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | package v2beta1
20 |
21 | type ALB2Expansion interface{}
22 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/gateway/v1alpha1/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // This package has the automatically generated typed clients.
20 | package v1alpha1
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/gateway/v1alpha1/fake/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | // Package fake has the automatically generated clients.
20 | package fake
21 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | package fake
20 |
21 | import (
22 | v1alpha1 "alauda.io/alb2/pkg/client/clientset/versioned/typed/gateway/v1alpha1"
23 | rest "k8s.io/client-go/rest"
24 | testing "k8s.io/client-go/testing"
25 | )
26 |
27 | type FakeGatewayV1alpha1 struct {
28 | *testing.Fake
29 | }
30 |
31 | func (c *FakeGatewayV1alpha1) TimeoutPolicies(namespace string) v1alpha1.TimeoutPolicyInterface {
32 | return &FakeTimeoutPolicies{c, namespace}
33 | }
34 |
35 | // RESTClient returns a RESTClient that is used to communicate
36 | // with API server by this client implementation.
37 | func (c *FakeGatewayV1alpha1) RESTClient() rest.Interface {
38 | var ret *rest.RESTClient
39 | return ret
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/client/clientset/versioned/typed/gateway/v1alpha1/generated_expansion.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by client-gen. DO NOT EDIT.
18 |
19 | package v1alpha1
20 |
21 | type TimeoutPolicyExpansion interface{}
22 |
--------------------------------------------------------------------------------
/pkg/client/listers/alauda/v2beta1/expansion_generated.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by lister-gen. DO NOT EDIT.
18 |
19 | package v2beta1
20 |
21 | // ALB2ListerExpansion allows custom methods to be added to
22 | // ALB2Lister.
23 | type ALB2ListerExpansion interface{}
24 |
25 | // ALB2NamespaceListerExpansion allows custom methods to be added to
26 | // ALB2NamespaceLister.
27 | type ALB2NamespaceListerExpansion interface{}
28 |
--------------------------------------------------------------------------------
/pkg/client/listers/gateway/v1alpha1/expansion_generated.go:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 | // Code generated by lister-gen. DO NOT EDIT.
18 |
19 | package v1alpha1
20 |
21 | // TimeoutPolicyListerExpansion allows custom methods to be added to
22 | // TimeoutPolicyLister.
23 | type TimeoutPolicyListerExpansion interface{}
24 |
25 | // TimeoutPolicyNamespaceListerExpansion allows custom methods to be added to
26 | // TimeoutPolicyNamespaceLister.
27 | type TimeoutPolicyNamespaceListerExpansion interface{}
28 |
--------------------------------------------------------------------------------
/pkg/config/const.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | var Alb2Finalizer = "alb2_instance.finalizer"
4 |
--------------------------------------------------------------------------------
/pkg/controller/ext/timeout/types/type.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | type TimeoutIngress struct {
4 | ProxyConnectTimeoutMs string `annotation:"proxy-connect-timeout" key:"proxy_connect_timeout_ms"`
5 | ProxySendTimeoutMs string `annotation:"proxy-send-timeout" key:"proxy_send_timeout_ms"`
6 | ProxyReadTimeoutMs string `annotation:"proxy-read-timeout" key:"proxy_read_timeout_ms"`
7 | }
8 |
9 | // k8s does not like float type, so we use uint instead
10 |
11 | // +k8s:deepcopy-gen=true
12 | type TimeoutCr struct {
13 | ProxyConnectTimeoutMs *uint `json:"proxy_connect_timeout_ms,omitempty" key:"proxy_connect_timeout_ms" trans:"time_from_string"`
14 | ProxySendTimeoutMs *uint `json:"proxy_send_timeout_ms,omitempty" key:"proxy_send_timeout_ms" trans:"time_from_string"`
15 | ProxyReadTimeoutMs *uint `json:"proxy_read_timeout_ms,omitempty" key:"proxy_read_timeout_ms" trans:"time_from_string"`
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/controller/ext/waf/types/waf_type.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | // +k8s:deepcopy-gen=true
4 | type WafCrConf struct {
5 | Enable bool `json:"enable"`
6 | // +optional
7 | WafConf `json:",inline"`
8 | }
9 |
10 | // +k8s:deepcopy-gen=true
11 | type WafConf struct {
12 | // +optional
13 | TransactionId string `json:"transactionId"` // could be ""
14 | // +optional
15 | UseCoreRules bool `json:"useCoreRules"`
16 | // +optional
17 | UseRecommend bool `json:"useRecommend"`
18 | // +optional
19 | CmRef string `json:"cmRef"` // ns/name#section
20 | }
21 |
22 | type WafInternal struct {
23 | Key string // 要跳转到的 nginx location
24 | Raw WafConf // 其他的waf的配置
25 | Snippet string // nginx location 的配置
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/controller/extctl/types/type.go:
--------------------------------------------------------------------------------
1 | package extctl
2 |
3 | import (
4 | "alauda.io/alb2/config"
5 | m "alauda.io/alb2/controller/modules"
6 | ct "alauda.io/alb2/controller/types"
7 | albv1 "alauda.io/alb2/pkg/apis/alauda/v1"
8 | ngt "alauda.io/alb2/pkg/controller/ngxconf/types"
9 | nv1 "k8s.io/api/networking/v1"
10 | )
11 |
12 | // ingress/alb/ft/rule 系列的插件。
13 | // TODO 应该能被用在gateway-api 上.
14 | type ExtensionInterface struct {
15 | IngressAnnotationToRule func(ing *nv1.Ingress, rindex int, pindex int, rule *albv1.Rule)
16 | IngressWithFtAnnotationToRule func(ft *albv1.Frontend, ing *nv1.Ingress, rindex int, pindex int, rule *albv1.Rule)
17 | ToInternalRule func(rule *m.Rule, r *ct.InternalRule)
18 | CollectRefs func(*ct.InternalRule, ct.RefMap)
19 | ToPolicy func(*ct.InternalRule, *ct.Policy, ct.RefMap)
20 | UpdateNgxTmpl func(tmpl_cfg *ngt.NginxTemplateConfig, alb *ct.LoadBalancer, cfg *config.Config)
21 | UpdatePolicyAfterUniq func(*ct.PolicyExt)
22 | InitL7Ft func(mft *m.Frontend, cft *ct.Frontend)
23 | NeedL7DefaultPolicy func(cft *ct.Frontend) (bool, string)
24 | InitL7DefaultPolicy func(cft *ct.Frontend, policy *ct.Policy)
25 | InitL4Ft func(mft *m.Frontend, cft *ct.Frontend)
26 | InitL4DefaultPolicy func(cft *ct.Frontend, policy *ct.Policy)
27 | ShouldMergeConfig func() bool
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/controller/ngxconf/nginx_param.go:
--------------------------------------------------------------------------------
1 | package ngxconf
2 |
3 | import (
4 | "os"
5 | "strconv"
6 |
7 | "alauda.io/alb2/config"
8 | . "alauda.io/alb2/pkg/controller/ngxconf/types"
9 | )
10 |
11 | func checkIPV6(enable bool) bool {
12 | if !enable {
13 | return false
14 | }
15 | if _, err := os.Stat("/proc/net/if_inet6"); err != nil {
16 | if os.IsNotExist(err) {
17 | return false
18 | }
19 | }
20 | return true
21 | }
22 |
23 | const (
24 | gzipTypes = "application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/javascript text/plain text/x-component"
25 | )
26 |
27 | func newNginxParam(cfg *config.Config) NginxParam {
28 | ngx := cfg.GetNginxCfg()
29 |
30 | cpu_preset := cfg.GetCpuPreset()
31 | work_limit := cfg.GetWorkerLimit()
32 | if work_limit == 0 {
33 | work_limit = 4
34 | }
35 | return NginxParam{
36 | EnablePrometheus: ngx.EnablePrometheus,
37 | EnableIPV6: checkIPV6(ngx.EnableIpv6),
38 | EnableHTTP2: ngx.EnableHttp2,
39 | CPUNum: strconv.Itoa(min(cpu_preset, work_limit)),
40 | MetricsPort: cfg.GetMetricsPort(),
41 | Backlog: ngx.BackLog,
42 | EnableGzip: ngx.EnableGzip,
43 | GzipLevel: 5,
44 | GzipMinLength: 256,
45 | GzipTypes: gzipTypes,
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/pkg/controller/ngxconf/ngxconf.go:
--------------------------------------------------------------------------------
1 | package ngxconf
2 |
3 | import (
4 | "bytes"
5 | _ "embed"
6 | "os"
7 | "text/template"
8 |
9 | . "alauda.io/alb2/pkg/controller/ngxconf/types"
10 | )
11 |
12 | //go:embed nginx.tmpl
13 | var NgxTmplEmbed string
14 |
15 | func RenderNgxRaw(config NginxTemplateConfig, tmpl string) (string, error) {
16 | t, err := template.New("nginx").Parse(tmpl)
17 | if err != nil {
18 | return "", err
19 | }
20 |
21 | var tpl bytes.Buffer
22 | if err := t.Execute(&tpl, config); err != nil {
23 | return "", err
24 | }
25 | return tpl.String(), nil
26 | }
27 |
28 | func RenderNgxFromFile(config NginxTemplateConfig, tmplPath string) (string, error) {
29 | tmplBytes, err := os.ReadFile(tmplPath)
30 | if err != nil {
31 | return "", err
32 | }
33 | return RenderNgxRaw(config, string(tmplBytes))
34 | }
35 |
36 | func RenderNginxConfigEmbed(config NginxTemplateConfig) (string, error) {
37 | return RenderNgxRaw(config, NgxTmplEmbed)
38 | }
39 |
--------------------------------------------------------------------------------
/pkg/operator/.dockerignore:
--------------------------------------------------------------------------------
1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
2 | # Ignore build and test binaries.
3 | bin/
4 | testbin/
5 |
--------------------------------------------------------------------------------
/pkg/operator/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Binaries for programs and plugins
3 | *.exe
4 | *.exe~
5 | *.dll
6 | *.so
7 | *.dylib
8 | bin
9 | testbin/*
10 |
11 | # Test binary, build with `go test -c`
12 | *.test
13 |
14 | # Output of the go coverage tool, specifically when used with LiteIDE
15 | *.out
16 |
17 | # Kubernetes Generated files - skip generated files, except for vendored files
18 |
19 | !vendor/**/zz_generated.*
20 |
21 | # editor and IDE paraphernalia
22 | .idea
23 | *.swp
24 | *.swo
25 | *~
26 |
--------------------------------------------------------------------------------
/pkg/operator/config/const.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | type valuePath struct {
4 | Value interface{}
5 | Path []string
6 | }
7 |
8 | var BindNic = valuePath{
9 | Value: "{}",
10 | Path: []string{"bindNIC"},
11 | }
12 |
13 | var DEFAULT_ENV = map[string]string{
14 | "ALB_IMAGE": "alb.img",
15 | "NGINX_IMAGE": "nginx.img",
16 | "LABEL_BASE_DOMAIN": "cpaas.io",
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/patch/configmap_patch.go:
--------------------------------------------------------------------------------
1 | package patch
2 |
3 | import (
4 | "context"
5 |
6 | cfg "alauda.io/alb2/pkg/operator/config"
7 | "sigs.k8s.io/controller-runtime/pkg/client"
8 |
9 | corev1 "k8s.io/api/core/v1"
10 | "k8s.io/apimachinery/pkg/types"
11 | "k8s.io/client-go/tools/cache"
12 | )
13 |
14 | func FindConfigmapPatch(ctx context.Context, cli client.Client, conf *cfg.ALB2Config, operator cfg.OperatorCfg) (hasPatch bool, configMap *corev1.ConfigMap, err error) {
15 | need := false
16 | name, ns := "", ""
17 | for _, p := range conf.Overwrite.Configmap {
18 | if p.Target == "" || p.Target == operator.Version {
19 | need = true
20 | ns, name, err = cache.SplitMetaNamespaceKey(p.Name)
21 | if err != nil {
22 | return false, nil, err
23 | }
24 | }
25 | }
26 | if !need {
27 | return false, nil, nil
28 | }
29 | cfg := &corev1.ConfigMap{}
30 | err = cli.Get(ctx, types.NamespacedName{Namespace: ns, Name: name}, cfg)
31 | if err != nil {
32 | return false, nil, err
33 | }
34 | return true, cfg, nil
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/patch/image_patch.go:
--------------------------------------------------------------------------------
1 | package patch
2 |
3 | import (
4 | cfg "alauda.io/alb2/pkg/operator/config"
5 | )
6 |
7 | // TODO 决定一个deployment具体要用那个image,和status中imagepatch字段,应该在一个地方来管理
8 | func GenImagePatch(conf *cfg.ALB2Config, operator cfg.OperatorCfg) (hasPatch bool, alb string, nginx string) {
9 | // 要升级的版本和patch中的版本一致
10 | hasPatch = false
11 | alb = operator.AlbImage
12 | nginx = operator.NginxImage
13 | for _, p := range conf.Overwrite.Image {
14 | if p.Target == "" || p.Target == operator.Version {
15 | if p.Alb != "" {
16 | hasPatch = true
17 | alb = p.Alb
18 | }
19 | if p.Nginx != "" {
20 | hasPatch = true
21 | nginx = p.Nginx
22 | }
23 | }
24 | }
25 | return hasPatch, alb, nginx
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/configmap/configmap.go:
--------------------------------------------------------------------------------
1 | package configmap
2 |
3 | import (
4 | v1 "k8s.io/api/core/v1"
5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6 | )
7 |
8 | type Template struct {
9 | namespace string
10 | name string
11 | }
12 |
13 | func NewTemplate(namespace string, name string) *Template {
14 | return &Template{
15 | namespace: namespace,
16 | name: name,
17 | }
18 | }
19 |
20 | func (t *Template) Generate(options ...Option) *v1.ConfigMap {
21 | cm := &v1.ConfigMap{
22 | TypeMeta: metav1.TypeMeta{
23 | Kind: "ConfigMap",
24 | APIVersion: "v1",
25 | },
26 | ObjectMeta: metav1.ObjectMeta{
27 | Name: t.name,
28 | Namespace: t.namespace,
29 | },
30 | Data: map[string]string{
31 | "http": HTTP,
32 | "http_server": HTTPSERVER,
33 | "grpc_server": GRPCSERVER,
34 | "stream-common": STREAM_COMMON,
35 | "stream-tcp": STREAM_TCP,
36 | "stream-udp": STREAM_UDP,
37 | "upstream": UPSTREAM,
38 | },
39 | }
40 | for _, op := range options {
41 | op(cm)
42 | }
43 | return cm
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/configmap/options.go:
--------------------------------------------------------------------------------
1 | package configmap
2 |
3 | import (
4 | v1 "k8s.io/api/core/v1"
5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6 | )
7 |
8 | type Option func(configMap *v1.ConfigMap)
9 |
10 | func WithBindNIC(nic string) Option {
11 | return func(configMap *v1.ConfigMap) {
12 | if configMap == nil {
13 | return
14 | }
15 | if configMap.Data == nil {
16 | configMap.Data = map[string]string{}
17 | }
18 | configMap.Data["bind_nic"] = nic
19 | }
20 | }
21 |
22 | func AddLabel(labels map[string]string) Option {
23 | return func(cm *v1.ConfigMap) {
24 | if cm == nil {
25 | return
26 | }
27 | if cm.Labels == nil {
28 | cm.Labels = map[string]string{}
29 | }
30 | for k, v := range labels {
31 | cm.Labels[k] = v
32 | }
33 | }
34 | }
35 |
36 | func SetOwnerRefs(reference []metav1.OwnerReference) Option {
37 | return func(configMap *v1.ConfigMap) {
38 | if configMap == nil {
39 | return
40 | }
41 | configMap.OwnerReferences = reference
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/gateway/options.go:
--------------------------------------------------------------------------------
1 | package gateway
2 |
3 | import gv1b1t "sigs.k8s.io/gateway-api/apis/v1"
4 |
5 | type Option func(service *gv1b1t.GatewayClass)
6 |
7 | func AddLabel(labels map[string]string) Option {
8 | return func(ic *gv1b1t.GatewayClass) {
9 | if ic == nil {
10 | return
11 | }
12 | if ic.Labels == nil {
13 | ic.Labels = map[string]string{}
14 | }
15 | for k, v := range labels {
16 | ic.Labels[k] = v
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/portinfo/options.go:
--------------------------------------------------------------------------------
1 | package portinfo
2 |
3 | import (
4 | v1 "k8s.io/api/core/v1"
5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6 | )
7 |
8 | type Option func(configMap *v1.ConfigMap)
9 |
10 | func defaultLabel(name string) Option {
11 | return func(cm *v1.ConfigMap) {
12 | if cm == nil {
13 | return
14 | }
15 | cm.Labels = map[string]string{
16 | "port-info": "true",
17 | "name": name,
18 | }
19 | }
20 | }
21 |
22 | func AddLabel(labels map[string]string) Option {
23 | return func(cm *v1.ConfigMap) {
24 | if cm == nil {
25 | return
26 | }
27 | if cm.Labels == nil {
28 | cm.Labels = map[string]string{}
29 | }
30 | for k, v := range labels {
31 | cm.Labels[k] = v
32 | }
33 | }
34 | }
35 |
36 | func SetOwnerRefs(reference []metav1.OwnerReference) Option {
37 | return func(configMap *v1.ConfigMap) {
38 | if configMap == nil {
39 | return
40 | }
41 | configMap.OwnerReferences = reference
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/portinfo/portinfo.go:
--------------------------------------------------------------------------------
1 | package portinfo
2 |
3 | import (
4 | "alauda.io/alb2/pkg/operator/toolkit"
5 | v1 "k8s.io/api/core/v1"
6 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7 | )
8 |
9 | type Template struct {
10 | namespace string
11 | name string
12 | data string
13 | }
14 |
15 | func NewTemplate(namespace string, name string, data string) *Template {
16 | return &Template{
17 | namespace: namespace,
18 | name: name,
19 | data: data,
20 | }
21 | }
22 |
23 | func (t *Template) Generate(options ...Option) *v1.ConfigMap {
24 | name := toolkit.FmtKeyBySep("-", t.name, "port-info")
25 | cm := &v1.ConfigMap{
26 | TypeMeta: metav1.TypeMeta{
27 | Kind: "ConfigMap",
28 | APIVersion: "v1",
29 | },
30 | ObjectMeta: metav1.ObjectMeta{
31 | Name: name,
32 | Namespace: t.namespace,
33 | },
34 | Data: map[string]string{
35 | "range": t.data,
36 | },
37 | }
38 | defaultOptions := []Option{
39 | defaultLabel(t.name),
40 | }
41 | for _, op := range defaultOptions {
42 | op(cm)
43 | }
44 | for _, op := range options {
45 | op(cm)
46 | }
47 | return cm
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/rbac/rbac_test.go:
--------------------------------------------------------------------------------
1 | package rbac
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestRoleFromJSON(t *testing.T) {
10 | rules := rulesOrPanic()
11 | t.Logf("role %v", CLUSTER_RULE_YAML)
12 | t.Logf("role %+v", rules)
13 | assert.Equal(t, len(rules) != 0, true)
14 | t.Logf("group %+v", rules[4])
15 | assert.Equal(t, rules[4].APIGroups[0], "discovery.k8s.io")
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/depl/resources/types/types.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | const (
4 | FMT_ROLE = "%s-clusterrole"
5 | FMT_ROLEBIND = "%s-clusterrolebind"
6 | FMT_SA = "%s-serviceaccount"
7 | )
8 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/scheme.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | albv1 "alauda.io/alb2/pkg/apis/alauda/v1"
5 | albv2 "alauda.io/alb2/pkg/apis/alauda/v2beta1"
6 | appsv1 "k8s.io/api/apps/v1"
7 | coov1 "k8s.io/api/coordination/v1"
8 | corev1 "k8s.io/api/core/v1"
9 | netv1 "k8s.io/api/networking/v1"
10 | rbacv1 "k8s.io/api/rbac/v1"
11 | "k8s.io/apimachinery/pkg/runtime"
12 | gv1 "sigs.k8s.io/gateway-api/apis/v1"
13 | gv1a2t "sigs.k8s.io/gateway-api/apis/v1"
14 | )
15 |
16 | //nolint:errcheck
17 | func InitScheme(scheme *runtime.Scheme) *runtime.Scheme {
18 | _ = albv2.AddToScheme(scheme)
19 | _ = appsv1.AddToScheme(scheme)
20 | _ = albv1.AddToScheme(scheme)
21 | _ = corev1.AddToScheme(scheme)
22 | _ = netv1.AddToScheme(scheme)
23 | _ = gv1.AddToScheme(scheme)
24 | _ = gv1a2t.AddToScheme(scheme)
25 | _ = rbacv1.AddToScheme(scheme)
26 | _ = coov1.AddToScheme(scheme)
27 | return scheme
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/setup.go:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import (
4 | "alauda.io/alb2/pkg/operator/config"
5 | "alauda.io/alb2/pkg/operator/controllers/depl"
6 | g "alauda.io/alb2/pkg/operator/controllers/standalone_gateway/gateway"
7 | gc "alauda.io/alb2/pkg/operator/controllers/standalone_gateway/gatewayclass"
8 | "github.com/go-logr/logr"
9 | ctrl "sigs.k8s.io/controller-runtime"
10 | )
11 |
12 | func Setup(mgr ctrl.Manager, cfg config.OperatorCfg, log logr.Logger) error {
13 | if err := (&depl.ALB2Reconciler{Client: mgr.GetClient(), OperatorCf: cfg, Log: log}).SetupWithManager(mgr); err != nil {
14 | return err
15 | }
16 | if err := (g.NewGatewayReconciler(mgr.GetClient(), cfg, log)).SetupWithManager(mgr); err != nil {
17 | return err
18 | }
19 | if err := (gc.NewGatewayClassReconciler(mgr.GetClient(), cfg, log)).SetupWithManager(mgr); err != nil {
20 | return err
21 | }
22 | return nil
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/standalone_gateway/gateway/cli_ext.go:
--------------------------------------------------------------------------------
1 | package standalone_gateway
2 |
3 | import (
4 | "context"
5 |
6 | "alauda.io/alb2/pkg/operator/config"
7 | "github.com/go-logr/logr"
8 | ctrl "sigs.k8s.io/controller-runtime"
9 | ctrcli "sigs.k8s.io/controller-runtime/pkg/client"
10 | gv1b1t "sigs.k8s.io/gateway-api/apis/v1"
11 | )
12 |
13 | type CliExt struct {
14 | ctrcli.Client
15 | log logr.Logger
16 | cfg config.OperatorCfg
17 | }
18 |
19 | func (c *CliExt) GetGateway(ctx context.Context, req ctrl.Request) (*gv1b1t.Gateway, error) {
20 | g := &gv1b1t.Gateway{}
21 | err := c.Get(ctx, ctrcli.ObjectKey{Namespace: req.Namespace, Name: req.Name}, g)
22 | if err != nil {
23 | return nil, err
24 | }
25 | return g, nil
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/operator/controllers/types/const.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | const (
4 | STAND_ALONE_GATEWAY_CLASS = "exclusive-gateway"
5 | FMT_STAND_ALONE_GATEWAY_CLASS_CTL_NAME = "alb2.gateway.%s/exclusive-gateway"
6 | )
7 |
8 | const FMT_ALB_REF = "alb.%s/alb-ref"
9 |
--------------------------------------------------------------------------------
/pkg/operator/toolkit/clustertype.go:
--------------------------------------------------------------------------------
1 | package toolkit
2 |
3 | import (
4 | "context"
5 |
6 | corev1 "k8s.io/api/core/v1"
7 | "sigs.k8s.io/controller-runtime/pkg/client"
8 | )
9 |
10 | func ClusterTypeIsCCE(cli client.Client, ctx context.Context) (bool, error) {
11 | cm := corev1.ConfigMap{}
12 | err := cli.Get(ctx, client.ObjectKey{Namespace: "kube-public", Name: "global-info"}, &cm)
13 | if err != nil {
14 | return false, err
15 | }
16 | return cm.Data["clusterType"] == "HuaweiCloudCCE", nil
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/operator/toolkit/meta.go:
--------------------------------------------------------------------------------
1 | package toolkit
2 |
3 | import (
4 | "strings"
5 |
6 | albv2 "alauda.io/alb2/pkg/apis/alauda/v2beta1"
7 |
8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9 | )
10 |
11 | // FmtKeyBySep is return string "key1+sep+key2"
12 | func FmtKeyBySep(sep string, key ...string) string {
13 | return strings.Join(key, sep)
14 | }
15 |
16 | func MakeOwnerRefs(alb2 *albv2.ALB2) []metav1.OwnerReference {
17 | return []metav1.OwnerReference{{
18 | APIVersion: albv2.SchemeGroupVersion.String(),
19 | Kind: albv2.ALB2Kind,
20 | Name: alb2.GetName(),
21 | UID: alb2.GetUID(),
22 | }}
23 | }
24 |
--------------------------------------------------------------------------------
/pkg/operator/toolkit/tools_test.go:
--------------------------------------------------------------------------------
1 | package toolkit
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestYamlToJson(t *testing.T) {
10 | y := `
11 | antiAffinityKey: system
12 | defaultSSLCert: cpaas-system/dex.tls
13 | defaultSSLStrategy: Both
14 | loadbalancerName: "global-alb2"
15 | metricsPort: 11782
16 | ingress: "true"
17 | albEnable: false
18 | projects:
19 | - cpaas-system
20 | `
21 | j, err := YamlToJson(y)
22 | assert.NoError(t, err)
23 | t.Logf("%s", j)
24 | assert.Equal(t, j, `{"albEnable":false,"antiAffinityKey":"system","defaultSSLCert":"cpaas-system/dex.tls","defaultSSLStrategy":"Both","ingress":"true","loadbalancerName":"global-alb2","metricsPort":11782,"projects":["cpaas-system"]}`)
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/utils/data_trans.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | )
7 |
8 | type ResolveAnnotationOpt struct {
9 | Prefix []string // 我们支持多个前缀,这样用户可以用我们自己的前缀来覆盖掉nginx的前缀,这样能保证他们的兼容性
10 | }
11 |
12 | func ResolverStructFromAnnotation(t interface{}, annotation map[string]string, opt ResolveAnnotationOpt) (bool, error) {
13 | t_type := reflect.TypeOf(t).Elem()
14 | t_val := reflect.ValueOf(t).Elem()
15 | has_annotation := false
16 | for i := 0; i < t_type.NumField(); i++ {
17 | t_field := t_type.Field(i)
18 | v_field := t_val.Field(i)
19 | if v_field.Kind() == reflect.Struct && t_field.Anonymous {
20 | has, err := ResolverStructFromAnnotation(v_field.Addr().Interface(), annotation, opt)
21 | if err != nil {
22 | return false, err
23 | }
24 | has_annotation = has_annotation || has
25 | }
26 |
27 | tag := t_field.Tag.Get("annotation")
28 | if tag == "" {
29 | continue
30 | }
31 | default_val := t_field.Tag.Get("default")
32 | // we only support string field to set
33 | if !(v_field.CanSet() && v_field.Kind() == reflect.String) {
34 | continue
35 | }
36 | resolved := false
37 | for _, prefix := range opt.Prefix {
38 | full_key := fmt.Sprintf("%s/%s", prefix, tag)
39 | if value, ok := annotation[full_key]; ok {
40 | v_field.SetString(value)
41 | resolved = true
42 | has_annotation = true
43 | break
44 | }
45 | }
46 | if !resolved {
47 | v_field.SetString(default_val)
48 | }
49 | }
50 | return has_annotation, nil
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/utils/metrics/metrics.go:
--------------------------------------------------------------------------------
1 | package metrics
2 |
3 | import "sync"
4 |
5 | var (
6 | _globalMu sync.RWMutex
7 | _globalM *metrics = nil
8 | )
9 |
10 | type metrics struct {
11 | data map[string]float64
12 | }
13 |
14 | func init() {
15 | _globalMu.Lock()
16 | defer _globalMu.Unlock()
17 | if _globalM != nil {
18 | return
19 | }
20 |
21 | _globalM = &metrics{data: map[string]float64{}}
22 | }
23 |
24 | // TODO 用 otel span..
25 |
26 | func Write(key string, value float64) {
27 | _globalMu.Lock()
28 | defer _globalMu.Unlock()
29 | _globalM.data[key] = value
30 | }
31 |
32 | func Read() map[string]float64 {
33 | _globalMu.RLock()
34 | defer _globalMu.RUnlock()
35 | return _globalM.data
36 | }
37 |
--------------------------------------------------------------------------------
/pkg/utils/test_utils/ing_utils/ing.go:
--------------------------------------------------------------------------------
1 | package ing_utils
2 |
3 | import (
4 | "context"
5 | "time"
6 |
7 | "alauda.io/alb2/config"
8 | ct "alauda.io/alb2/controller/types"
9 | "alauda.io/alb2/driver"
10 | ing "alauda.io/alb2/ingress"
11 | . "alauda.io/alb2/pkg/utils/test_utils"
12 | "github.com/go-logr/logr"
13 | "k8s.io/client-go/rest"
14 | )
15 |
16 | func SyncIngressAndGetPolicyFromK8s(rest *rest.Config, ns, name string, log logr.Logger) (*ct.NgxPolicy, error) {
17 | ctx := context.Background()
18 | cfg := config.Mock(name, ns)
19 | drv, err := driver.NewDriver(driver.DrvOpt{Ctx: ctx, Cf: rest, Opt: driver.Cfg2opt(cfg)})
20 | if err != nil {
21 | return nil, err
22 | }
23 | ing_ctl := ing.NewController(drv, drv.Informers, cfg, log)
24 | ing_ctl.SyncAll()
25 | time.Sleep(1 * time.Second)
26 | go ing_ctl.RunWorker()
27 | for i := 0; i < 10; i++ {
28 | if ing_ctl.GetWorkqueueLen() == 0 {
29 | break
30 | }
31 | time.Sleep(1 * time.Second) // wait rule sync
32 | }
33 | time.Sleep(3 * time.Second) // wait rule sync
34 | policy, err := GetPolicy(PolicyGetCtx{
35 | Ctx: ctx, Name: name, Ns: ns, Drv: drv, L: log,
36 | Cfg: cfg,
37 | })
38 | if err != nil {
39 | return nil, err
40 | }
41 | return policy, nil
42 | }
43 |
--------------------------------------------------------------------------------
/pkg/utils/test_utils/mock_svc.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import otu "alauda.io/alb2/utils/test_utils"
4 |
5 | type MockSvc struct {
6 | Ns string
7 | Name string
8 | Port []int
9 | Ep []string
10 | }
11 |
12 | func (m MockSvc) GenYaml() string {
13 | return otu.Template(`
14 | apiVersion: v1
15 | kind: Service
16 | metadata:
17 | name: {{.name}}
18 | namespace: {{.ns}}
19 | spec:
20 | clusterIP: 10.0.0.254
21 | internalTrafficPolicy: Cluster
22 | sessionAffinity: None
23 | type: ClusterIP
24 | ipFamilies:
25 | - IPv4
26 | ipFamilyPolicy: SingleStack
27 | ports:
28 | {{ range $p := .port }}
29 | - name: port-{{$p}}
30 | port: {{$p}}
31 | protocol: TCP
32 | targetPort: {{$p}}
33 | {{ end }}
34 | ---
35 | apiVersion: v1
36 | kind: Endpoints
37 | metadata:
38 | name: {{.name}}
39 | namespace: {{.ns}}
40 | subsets:
41 | {{ range $ip := .ep }}
42 | - addresses:
43 | - ip: {{$ip}}
44 | ports:
45 | {{ range $p := $.port }}
46 | - name: port-{{$p}}
47 | port: {{$p}}
48 | protocol: TCP
49 | {{- end -}}
50 | {{- end -}}
51 | `, map[string]interface{}{"name": m.Name, "ns": m.Ns, "port": m.Port, "ep": m.Ep})
52 | }
53 |
--------------------------------------------------------------------------------
/pkg/utils/test_utils/ngxconf_parser_ext_test.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestParseNgxConfig(t *testing.T) {
10 | cfg := `
11 |
12 | events {
13 | multi_accept on;
14 | worker_connections 51200;
15 | }
16 |
17 | http {
18 | server {
19 | listen 127.0.0.1:81;
20 | listen 192.168.2.3:81;
21 | }
22 | }
23 |
24 | stream {
25 | server {
26 | listen 127.0.0.1:80 udp;
27 | listen 192.168.2.3:80 udp;
28 | }
29 | server {
30 | listen 127.0.0.1:80;
31 | listen 192.168.2.3:80;
32 | }
33 | }
34 | `
35 | listen, err := PickStreamServerListen(cfg)
36 | assert.NoError(t, err)
37 | assert.Equal(t, listen[0], "127.0.0.1:80 udp")
38 | assert.Equal(t, listen[1], "192.168.2.3:80 udp")
39 | assert.Equal(t, listen[2], "127.0.0.1:80")
40 | assert.Equal(t, listen[3], "192.168.2.3:80")
41 | assert.Equal(t, len(listen), 4)
42 |
43 | listen, err = PickHttpServerListen(cfg)
44 | assert.NoError(t, err)
45 | assert.Equal(t, listen[0], "127.0.0.1:81")
46 | assert.Equal(t, listen[1], "192.168.2.3:81")
47 | assert.Equal(t, len(listen), 2)
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/utils/util.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "crypto/sha256"
5 | "encoding/hex"
6 | "fmt"
7 | "strings"
8 |
9 | "sigs.k8s.io/controller-runtime/pkg/client"
10 | )
11 |
12 | func ToBoolOr(x string, backup bool) bool {
13 | if x == "" {
14 | return backup
15 | }
16 | return strings.ToLower(strings.TrimSpace(x)) == "true"
17 | }
18 |
19 | func MergeMap(a map[string]string, b map[string]string) map[string]string {
20 | ret := map[string]string{}
21 | for k, v := range a {
22 | ret[k] = v
23 | }
24 | for k, v := range b {
25 | ret[k] = v
26 | }
27 | return ret
28 | }
29 |
30 | func HashBytes(s []byte) string {
31 | h := sha256.New()
32 | h.Write(s)
33 | return hex.EncodeToString(h.Sum(nil))
34 | }
35 |
36 | func Hash(s string) string {
37 | h := sha256.New()
38 | h.Write([]byte(s))
39 | return hex.EncodeToString(h.Sum(nil))
40 | }
41 |
42 | func ParseStringToObjectKey(key string) (client.ObjectKey, error) {
43 | parts := strings.Split(key, "/")
44 | if len(parts) != 2 {
45 | return client.ObjectKey{}, fmt.Errorf("invalid key format: %s", key)
46 | }
47 | return client.ObjectKey{
48 | Namespace: parts[0],
49 | Name: parts[1],
50 | }, nil
51 | }
52 |
--------------------------------------------------------------------------------
/scripts/alb-ai-actions.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function alb-ai-review() {
4 | # 为ai-review而优化的commit workflow
5 | # 不在两个commit中改同一个文件
6 | # commit message 作为prompt的一部分
7 | local commit=$1
8 | if [ -z "$commit" ]; then
9 | commit=$(git log --pretty=format:"%H %s" origin/master..HEAD | fzf | awk '{print $1}')
10 | fi
11 | local msg=$(git show -s --format=%s $commit | sed 's/\n/_/g' | sed 's/\s/_/g' | sed 's|/|_|g')
12 | echo "review $commit $msg"
13 | local full_msg=$(git show -s --format=%B $commit)
14 | local prompt=$(
15 | cat </dev/null 2>&1
29 | local p="./.review/$commit-$msg.review.prompt"
30 | echo "$prompt" >$p
31 | git show $commit >>$p
32 | echo "$p $(ls -alh $p)"
33 | return
34 | }
35 |
--------------------------------------------------------------------------------
/scripts/alb-checklist-actions.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function alb-sync-to-checklist() {
4 | local target="$1"
5 | for p in ./migrate/checklist/custom/*; do
6 | md5sum $p
7 | cp -r $p $target/checklist/custom/
8 | done
9 | echo "====="
10 | for p in $target/checklist/custom/*; do
11 | md5sum $p
12 | done
13 | }
14 |
15 | function alb-sync-from-checklist() {
16 | local target="$1"
17 | for p in $target/checklist/custom/*; do
18 | md5sum $p
19 | cp $p ./migrate/checklist/custom/
20 | done
21 | echo "====="
22 | for p in ./migrate/checklist/custom/*; do
23 | md5sum $p
24 | done
25 | }
26 |
27 | function alb-checklist-test() (
28 | ginkgo -v ./test/checklist
29 | )
30 |
--------------------------------------------------------------------------------
/scripts/alb-dev-actions.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # shellcheck disable=SC2046,SC2086,SC1091,SC2005
3 |
4 | export GOPROXY=https://goproxy.cn,https://build-nexus.alauda.cn/repository/golang,direct
5 |
6 | function _current_file() {
7 | local cf="${BASH_SOURCE[0]}"
8 | if [ -z "$cf" ]; then
9 | cf="$1"
10 | fi
11 | echo $cf
12 | }
13 |
14 | function _alb_dir() (
15 | echo $(dirname $(cd $(dirname $(_current_file $1)) && pwd))
16 | )
17 |
18 | CUR_ALB_BASE=$(_alb_dir "$0")
19 |
20 | source $CUR_ALB_BASE/scripts/alb-test-actions.sh
21 | source $CUR_ALB_BASE/scripts/alb-lint-actions.sh
22 | source $CUR_ALB_BASE/scripts/alb-build-actions.sh
23 | source $CUR_ALB_BASE/scripts/alb-env-actions.sh
24 | source $CUR_ALB_BASE/scripts/alb-codegen-actions.sh
25 | source $CUR_ALB_BASE/scripts/alb-perf-actions.sh
26 | source $CUR_ALB_BASE/template/actions/alb-nginx.sh
27 | source $CUR_ALB_BASE/scripts/alb-github-actions.sh
28 | source $CUR_ALB_BASE/scripts/alb-ai-actions.sh
29 |
30 | function alb-dev-install() (
31 | # yq => yq (https://github.com/mikefarah/yq/) version > 4
32 | return
33 | )
34 |
35 | function alb-list-todo-all() (
36 | rg TODO
37 | )
38 |
39 | function alb-list-todo-cur() (
40 | git diff $(git merge-base master HEAD)..HEAD | grep -i "TODO"
41 | )
42 |
43 | function alb-replace-alb() (
44 | alb-static-build
45 | local alb_pod=$(kubectl get po -n cpaas-system --no-headers | grep $1 | awk '{print $1}')
46 | kubectl cp $PWD/bin/alb cpaas-system/$alb_pod:/alb/ctl/alb -c alb2
47 | )
48 |
--------------------------------------------------------------------------------
/scripts/boilerplate.go.txt:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 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 |
--------------------------------------------------------------------------------
/scripts/custom-ci-action.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function init() {
4 | yum update
5 | yum install docker
6 | # make sure docker work
7 | docker pull registry.alauda.cn:60080/acp/alb-nginx:v3.12.2
8 | # musl
9 | # https://rhel.pkgs.org/7/forensics-x86_64/musl-libc-1.2.1-1.el7.x86_64.rpm.html
10 | # kind
11 | # helm
12 | # kubectl
13 | # yq
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/scripts/go-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | pwd
3 | sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4 | apk add bash curl jq
5 | bash -c 'ALB=$PWD;source ./scripts/alb-dev-actions.sh;alb-test-all-in-ci-golang'
6 |
--------------------------------------------------------------------------------
/scripts/kubescape.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | res = JSON.parse(fs.readFileSync('./results.json', 'utf8'))
3 | out = []
4 | for (i of res.results) {
5 | cs = []
6 | for (c of i.controls) {
7 | if (c.status.status != "passed") {
8 | // console.log(c.status);
9 | cs.push(c)
10 | }
11 | }
12 | i.controls = cs
13 | if (cs.length > 0) {
14 | out.push(i)
15 | }
16 | }
17 | console.log(JSON.stringify(out, null, 4));
--------------------------------------------------------------------------------
/scripts/nginx-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | pwd
3 | sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4 | apk add bash curl jq
5 | bash -c 'ALB=$PWD;source ./template/actions/alb-nginx.sh;alb-test-all-in-ci-nginx'
6 |
--------------------------------------------------------------------------------
/scripts/run-like-ci-go.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -x
3 | # proxy=""
4 | # if [ -n "$USE_PROXY" ]; then
5 | # proxy="--network=host -e http_proxy=$HTTP_PROXY -e https_proxy=$HTTPS_PROXY "
6 | # fi
7 | base=${1-$(cat ./Dockerfile | grep GO_BUILD_BASE | awk -F = '{print $2}')}
8 | echo "base $base"
9 | platform=${MATRIX_PLATFORM:-linux/amd64}
10 | echo "platform -- $platform --"
11 | docker run --network=host -v $PWD:/acp-alb-test --platform $platform -e ALB_ONLINE=$ALB_ONLINE -t $base sh -c "cd /acp-alb-test ;/acp-alb-test/scripts/go-test.sh"
12 |
--------------------------------------------------------------------------------
/scripts/run-like-ci-kind.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function kind-e2e-local() (
4 | go test -c alauda.io/alb2/test/kind/e2e
5 | mv ./test.test ./alb-kind-e2e
6 | export ALB_SUFFIX=ka
7 | echo $ALB_SUFFIX
8 | md5sum ./alb-kind-e2e
9 | export ALB_KIND_E2E_CHART=v3.13.0-alpha.11
10 | export ALB_CI_ROOT=/tmp/alb-kind
11 | mkdir -p $ALB_CI_ROOT
12 | local base="$ALB_CI_ROOT/$ALB_SUFFIX"
13 | mkdir -p $base
14 | mv ./alb-kind-e2e $base
15 | cd $base
16 | export ALB_TEST_BASE=$base
17 | ./alb-kind-e2e
18 | )
19 |
20 | kind-e2e-local $@
21 |
--------------------------------------------------------------------------------
/scripts/run-like-ci-nginx.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # test current nginx
3 | # we should build a nginx image first then use this image to test.
4 | tag=$(yq '.global.images.nginx.tag' ./deploy/chart/alb/values.yaml)
5 | image=build-harbor.alauda.cn/acp/alb2:$tag
6 | if [ -n "$1" ] && [ "$1" != "cur" ]; then
7 | image="$1"
8 | fi
9 | # image=alb-nginx:test
10 |
11 | platform=${MATRIX_PLATFORM:-linux/amd64}
12 | echo "platform $platform"
13 | if [ "$2" == "shell" ]; then
14 | docker run --user root --network=host --platform $platform -v $PWD:/acp-alb-test -it $image sh
15 | else
16 | docker run --user root --network=host --platform $platform -v $PWD:/acp-alb-test -t $image sh -c 'cd /acp-alb-test ;/acp-alb-test/scripts/nginx-test.sh'
17 | fi
18 |
--------------------------------------------------------------------------------
/scripts/yaml/crds/extra/mock/clustercert.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apiextensions.k8s.io/v1
3 | kind: CustomResourceDefinition
4 | metadata:
5 | name: clustercredentials.platform.tkestack.io
6 | spec:
7 | group: platform.tkestack.io
8 | names:
9 | kind: ClusterCredential
10 | listKind: ClusterCredentialList
11 | plural: clustercredentials
12 | shortNames:
13 | - cc
14 | singular: clustercredential
15 | scope: Cluster
16 | versions:
17 | - name: v1
18 | schema:
19 | openAPIV3Schema:
20 | type: object
21 | properties:
22 | apiVersion:
23 | type: string
24 | kind:
25 | type: string
26 | metadata:
27 | type: object
28 | spec:
29 | type: object
30 | properties:
31 | token:
32 | type: string
33 | served: true
34 | storage: true
--------------------------------------------------------------------------------
/scripts/yaml/crds/v1beta1/alb2-crd.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apiextensions.k8s.io/v1beta1
2 | kind: CustomResourceDefinition
3 | metadata:
4 | name: alaudaloadbalancer2.crd.alauda.io
5 | spec:
6 | group: crd.alauda.io
7 | version: v1
8 | versions:
9 | - name: v1
10 | served: true
11 | storage: true
12 | scope: Namespaced
13 | subresources:
14 | status: {}
15 | names:
16 | plural: alaudaloadbalancer2
17 | singular: alaudaloadbalancer2
18 | kind: ALB2
19 | shortNames:
20 | - alb2
21 | validation:
22 | openAPIV3Schema:
23 | properties:
24 | spec:
25 | description: spec contains specification parameters for a alb2 resource
26 | type: object
27 | properties:
28 | address:
29 | description: address is used to shown access address if no domain
30 | type: string
31 | bind_address:
32 | description: deprecated field
33 | type: string
34 | type:
35 | description: deprecated field
36 | type: string
37 | domains:
38 | description: deprecated field
39 | anyOf:
40 | - type: array
41 | items:
42 | type: string
43 | - type: null
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | # sonar.projectVersion=v3.12-1-g7651640
2 | # if you want disabled the DTD verification for a proxy problem for example, true by default
3 | sonar.coverage.dtdVerification=false
4 | # JUnit like test report, default value is test.xml
5 | sonar.sources=./
6 | sonar.test=./
7 | sonar.exclusions=test/**,**/*_test.go,pkg/apis/**,pkg/client/**
8 | sonar.test.inclusions=./**/*_test.go
9 | sonar.test.exclusions=vendor/**
10 | # sonar.golint.reportPath=report.xml
11 | # sonar.coverage.reportPath=coverage.xml
12 | # sonar.test.reportPath=test.xml
13 | sonar.go.coverage.reportPaths=coverage.txt
14 | # sonar.host.url=https://build-sonar.alauda.cn
15 | # sonar.branch.name=master
16 | # sonar.login=f09bc48196cea04ffce476f1c178055b8da2820e
17 | sonar.links.scm=https://gitlab-ce.alauda.cn/container-platform/alb2
18 |
--------------------------------------------------------------------------------
/template/Dockerfile.debug:
--------------------------------------------------------------------------------
1 | FROM alpine:latest
2 | RUN echo "Hello, World!"
3 |
--------------------------------------------------------------------------------
/template/actions/dev.actions.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function ang-build-nginx-image() {
4 | local tag="local"
5 | if [[ -n "$1" ]]; then
6 | tag=$1
7 | fi
8 | echo "build alb-nginx local"
9 | docker build -t build-harbor.alauda.cn/acp/alb-nginx:$tag -f ./template/Dockerfile .
10 | docker tag build-harbor.alauda.cn/acp/alb-nginx:$tag registry.alauda.cn:60080/acp/alb-nginx:$tag
11 | }
12 |
13 | function ang-local-test() {
14 | if [ -d ./.t ]; then
15 | sudo rm -rf ./.t
16 | fi
17 | docker run --user root -it -e SKIP_INSTALL_NGINX_TEST_DEP=true -v $PWD/.t:/t/ -v $PWD/template/nginx/:/alb/nginx/ -v $PWD:/acp-alb-test build-harbor.alauda.cn/acp/alb-nginx-tester:local sh -c 'cd /acp-alb-test ;/acp-alb-test/scripts/nginx-test.sh'
18 | }
19 |
20 | function ang-start() (
21 | mkdir -p ./.ang/logs
22 | local alb=$PWD
23 | local chaos=$alb/template/actions/chaos
24 | cd ./.ang
25 | cp $chaos/alb.nginx.conf ./
26 | ln -s $alb ./alb2
27 | configmap_to_file $alb/template/tweak
28 | sed -i '/proxy_send*/d' $alb/template/tweak/http.conf
29 | sed -i '/proxy_read*/d' $alb/template/tweak/http.conf
30 | export SYNC_POLICY_INTERVAL=1
31 | export CLEAN_METRICS_INTERVAL=2592000
32 | export NEW_POLICY_PATH=$chaos/policy.json
33 | export DEFAULT_SSL_STRATEGY=NEVER
34 | export INGRESS_HTTPS_PORT=443
35 | nginx -p $PWD -c $PWD/alb.nginx.conf
36 | return
37 | )
38 |
39 | function nb-start-alb() {
40 | return
41 | }
42 |
--------------------------------------------------------------------------------
/template/actions/test-nginx-in-ci.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | CFD="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
3 | ALB=$(realpath $CFD/../../)
4 | source $CFD/alb-nginx.sh
5 |
6 | test-nginx-in-ci
7 |
--------------------------------------------------------------------------------
/template/chaos/break/README.md:
--------------------------------------------------------------------------------
1 | 测试在不同阶段中断对alb重试的影响
--------------------------------------------------------------------------------
/template/chaos/tl502/README.md:
--------------------------------------------------------------------------------
1 | https://jira.alauda.cn/browse/ACP-30564
2 | 测试
3 | - 在发了rst之后会不会继续发包
4 | - 在收到了rst之后后不会报502
5 |
6 |
7 | wrk -d3s -c1 -t1 -s ./x.lua http://127.0.0.1 -- 6
8 |
--------------------------------------------------------------------------------
/template/chaos/tl502/demo.conf:
--------------------------------------------------------------------------------
1 | worker_processes 1;
2 | daemon off;
3 | pid nginx.pid;
4 | env POD_NAME;
5 |
6 | events {
7 | worker_connections 1024;
8 | }
9 |
10 | http {
11 | access_log /dev/stdout ;
12 | error_log /dev/stdout info;
13 | server {
14 | listen 80;
15 | listen [::]:80;
16 | location / {
17 | content_by_lua_block {
18 | local h, err = ngx.req.get_headers()
19 | if err ~=nil then
20 | ngx.say("err: "..tostring(err))
21 | end
22 | for k, v in pairs(h) do
23 | ngx.say(tostring(k).." : "..tostring(v))
24 | end
25 | ngx.say("http client-ip "..ngx.var.remote_addr.." client-port "..ngx.var.remote_port.." server-ip "..ngx.var.server_addr.." server-port "..ngx.var.server_port)
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/template/chaos/tl502/test.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 | local u = require "util"
3 |
4 | function _M.as_backend()
5 | ngx.say "ok"
6 |
7 | end
8 | function _M.as_backend_1_0()
9 | ngx.say "ok"
10 | end
11 | function _M.as_backend_1_1()
12 | ngx.say "ok"
13 | end
14 |
15 | function _M.test()
16 | -- do
17 | -- local httpc = require"resty.http".new()
18 | -- local res, err = httpc:request("http://127.0.0.1:80/1_0/1")
19 | -- u.logs(res, err)
20 | -- local res, err = httpc:request("http://127.0.0.1:80/1_0/2")
21 | -- u.logs(res, err)
22 | -- end
23 | -- do
24 | -- local httpc = require"resty.http".new()
25 | -- local res, err = httpc:request("http://127.0.0.1:80/1_1/1")
26 | -- u.logs(res, err)
27 | -- local res, err = httpc:request_uri("http://127.0.0.1:80/1_1/2")
28 | -- u.logs(res, err)
29 | -- end
30 | do
31 | local httpc = require"resty.http".new()
32 | local res, err = httpc:request_uri("http://127.0.0.1:80/default/1", {method = "POST", body = "xx"})
33 | u.logs(res, err)
34 | local res, err = httpc:request_uri("http://127.0.0.1:80/default/2", {method = "POST", body = "xx"})
35 | u.logs(res, err)
36 |
37 | ngx.sleep(3000)
38 | end
39 | end
40 | return _M
41 |
--------------------------------------------------------------------------------
/template/nginx/lua/README.md:
--------------------------------------------------------------------------------
1 | ## how to write test
2 | write test under ALB/alb-nginx/t
3 | ALB/alb-nginx/t/ping.t is a good example
4 |
5 | ## how to lint/format
6 | use alb-lua-format-check action on alb-dev-action.sh.
7 | update TOUCHED_LUA_FILE when you update a lua file.
8 |
9 | ## how to write doc
10 | https://keplerproject.github.io/luadoc/manual.html
11 |
--------------------------------------------------------------------------------
/template/nginx/lua/balancer/alb_chash.lua:
--------------------------------------------------------------------------------
1 | local balancer_resty = require "balancer.resty"
2 | local resty_chash = require "resty.chash"
3 | local common = require "utils.common"
4 | local bc = require "balancer.common"
5 |
6 | local _M = balancer_resty:new({ factory = resty_chash, name = "chash" })
7 |
8 | function _M.new(self, backend)
9 | local nodes = bc.get_nodes(backend)
10 | local o = {
11 | instance = self.factory:new(nodes),
12 | }
13 | if backend["session_affinity_policy"] == "sip-hash" then
14 | o.hash_by = "$remote_addr"
15 | end
16 | setmetatable(o, self)
17 | self.__index = self
18 | return o
19 | end
20 |
21 | function _M.balance(self)
22 | local key = common.lua_ngx_var(self.hash_by)
23 | return self.instance:find(key)
24 | end
25 |
26 | return _M
27 |
--------------------------------------------------------------------------------
/template/nginx/lua/balancer/common.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 | -- {
3 | -- "mode": "http",
4 | -- "session_affinity_attribute": "",
5 | -- "name": "calico-new-yz-alb-09999-eb1a18d0-8d44-4100-bbb8-93db3c02c482",
6 | -- "session_affinity_policy": "",
7 | -- "backends": [
8 | -- {
9 | -- "ns": "default",
10 | -- "svc": "xx",
11 | -- "port": 80,
12 | -- "address": "10.16.12.11",
13 | -- "weight": 100
14 | -- }
15 | -- ]
16 | -- }
17 |
18 | function _M.node_key(ep)
19 | return ep.address .. ":" .. ep.port
20 | end
21 | function _M.get_nodes(backend)
22 | local nodes = {}
23 |
24 | for _, endpoint in ipairs(backend.backends) do
25 | local endpoint_string = _M.node_key(endpoint)
26 | nodes[endpoint_string] = endpoint.weight
27 | end
28 | return nodes
29 | end
30 |
31 | return _M
32 |
--------------------------------------------------------------------------------
/template/nginx/lua/balancer/resty.lua:
--------------------------------------------------------------------------------
1 | local common = require "utils.common"
2 | local bc = require "balancer.common"
3 | local new_tab = require "table.new"
4 |
5 | local string_format = string.format
6 | local ngx_log = ngx.log
7 | local INFO = ngx.INFO
8 |
9 | local _M = {}
10 |
11 | function _M.new(self, o)
12 | o = o or {}
13 | setmetatable(o, self)
14 | self.__index = self
15 | return o
16 | end
17 |
18 | local function init_peer_map(backend)
19 | local peer_map = new_tab(0, #backend.backends)
20 | for i, node in ipairs(backend.backends) do
21 | peer_map[bc.node_key(node)] = i
22 | end
23 | return peer_map
24 | end
25 |
26 | function _M.sync(self, backend)
27 | local nodes = bc.get_nodes(backend)
28 | self.backend = backend
29 | if self.backend.peer_map == nil then
30 | self.backend.peer_map = init_peer_map(backend)
31 | end
32 | local changed = not common.table_equals(self.instance.nodes, nodes)
33 | if not changed then
34 | return
35 | end
36 |
37 | ngx_log(INFO, string_format("[%s] nodes have changed for backend %s", self.name, backend.name))
38 | self.backend.peer_map = init_peer_map(backend)
39 | self.instance:reinit(nodes)
40 | end
41 |
42 | function _M.get_peer_conf(self, peer)
43 | local index = self.backend.peer_map[peer]
44 | return self.backend.backends[index]
45 | end
46 |
47 | return _M
48 |
--------------------------------------------------------------------------------
/template/nginx/lua/balancer/round_robin.lua:
--------------------------------------------------------------------------------
1 | local balancer_resty = require "balancer.resty"
2 | local resty_roundrobin = require "resty.roundrobin"
3 | local bc = require "balancer.common"
4 |
5 | local _M = balancer_resty:new({ factory = resty_roundrobin, name = "round_robin" })
6 |
7 | function _M.new(self, backend)
8 | local nodes = bc.get_nodes(backend)
9 | local o = {
10 | instance = self.factory:new(nodes),
11 | }
12 | setmetatable(o, self)
13 | self.__index = self
14 | return o
15 | end
16 |
17 | function _M.balance(self)
18 | return self.instance:find()
19 | end
20 |
21 | return _M
22 |
--------------------------------------------------------------------------------
/template/nginx/lua/config/README.md:
--------------------------------------------------------------------------------
1 | this module include thing related to push our policy.json to each worker's mlcache.
2 |
--------------------------------------------------------------------------------
/template/nginx/lua/config/conf.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local os_getenv = os.getenv
3 |
4 | local _M = {}
5 |
6 | _M.default_ssl_strategy = os_getenv("DEFAULT_SSL_STRATEGY")
7 | _M.default_https_port = os_getenv("INGRESS_HTTPS_PORT")
8 |
9 | return _M
10 |
--------------------------------------------------------------------------------
/template/nginx/lua/ctx/alb_ctx.lua:
--------------------------------------------------------------------------------
1 | --- per request ctx
2 |
3 | local _M = {}
4 | local str_sub = string.sub
5 | local var_proxy = require "ctx.var_proxy"
6 |
7 | ---@class BackendConf
8 | ---@field address string
9 | ---@field port number
10 | ---@field weight number
11 | ---@field svc string?
12 | ---@field ns string?
13 |
14 | ---@class PeerConf
15 | ---@field peer string
16 | ---@field conf BackendConf the policy.backend_groups[upstream].backends[current_backend_index]
17 |
18 |
19 | ---@class AlbCtx
20 | ---@field matched_policy Policy
21 | ---@field send_count number retry_count
22 | ---@field peer PeerConf valid only after the balance phase
23 | ---@field var table var proxy
24 | ---@field otel OtelCtx?
25 | ---@field auth AuthCtx?
26 |
27 | ---@param ctx AlbCtx
28 | function _M.get_last_upstream_status(ctx)
29 | -- $upstream_status maybe including multiple status, only need the last one
30 | return tonumber(str_sub(ctx.var["upstream_status"] or "", -3))
31 | end
32 |
33 | ---@return AlbCtx
34 | function _M.new()
35 | return {
36 | var = var_proxy.new(),
37 | send_count = 0,
38 | matched_policy = nil,
39 | }
40 | end
41 |
42 | ---@return AlbCtx
43 | function _M.get_alb_ctx()
44 | return ngx.ctx.alb_ctx
45 | end
46 |
47 | return _M
48 |
--------------------------------------------------------------------------------
/template/nginx/lua/error.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local _M = {}
3 | local ngx = ngx
4 | local common = require "utils.common"
5 | local subsys = require "utils.subsystem"
6 |
7 | local ErrReason = "X-ALB-ERR-REASON"
8 |
9 | _M.UnknowStickyPolicy = "UnknowStickyPolicy"
10 | _M.InvalidUpstream = "InvalidUpstream"
11 | _M.InvalidBalancer = "InvalidBalancer"
12 | _M.BackendError = "BackendError"
13 | _M.TimeoutViaAlb = "TimeoutViaAlb"
14 | _M.TimeoutViaBackend = "TimeoutViaBackend"
15 | _M.AUTHFAIL = "AuthFail"
16 |
17 | ---comment
18 | -- exit with code 500 Internal Server Error
19 | ---@param reason string
20 | ---@param msg? string
21 | function _M.exit(reason, msg)
22 | _M.exit_with_code(reason, msg, ngx.ERROR)
23 | end
24 |
25 | function _M.exit_with_code(reason, msg, code)
26 | if msg ~= nil then
27 | reason = reason .. " : " .. tostring(msg)
28 | end
29 | ngx.log(ngx.ERR, reason)
30 | if subsys.is_http_subsystem() then
31 | ngx.header[ErrReason] = reason
32 | ngx.ctx.is_alb_err = true
33 | ngx.status = code
34 | if ngx.ctx.alb_ctx.var["http_cpaas_trace"] == "true" then
35 | ngx.header["x-cpaas-trace"] = common.json_encode(ngx.ctx.alb_ctx.var.trace, false)
36 | end
37 | ngx.exit(ngx.HTTP_OK)
38 | end
39 | if subsys.is_stream_subsystem() then
40 | ngx.exit(ngx.ERROR)
41 | end
42 | end
43 |
44 | function _M.http_backend_error(_, msg)
45 | ngx.header[ErrReason] = _M.BackendError .. " : " .. tostring(msg)
46 | end
47 |
48 | return _M
49 |
--------------------------------------------------------------------------------
/template/nginx/lua/l4_preread.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local ngx = ngx
3 | local ngx_var = ngx.var
4 | local ngx_log = ngx.log
5 | local e = require("error")
6 |
7 | local upstream = require "match_engine.upstream"
8 | local albctx = require "ctx.alb_ctx"
9 |
10 | local subsystem = ngx.config.subsystem
11 | ngx.ctx.alb_ctx = albctx.new()
12 | local port = tonumber(ngx_var.server_port)
13 | if port == nil then
14 | local msg = "invalid server_port " .. tostring(ngx_var.server_port)
15 | return e.exit(e.InvalidUpstream, msg)
16 | end
17 |
18 | local t_upstream, matched_policy, errmsg = upstream.get_upstream(subsystem, ngx_var.protocol, port)
19 |
20 | if t_upstream == nil then
21 | local msg = "alb upstream not found "
22 | return e.exit(e.InvalidUpstream, msg)
23 | end
24 |
25 | if matched_policy == nil then
26 | local msg = "alb policy not found"
27 | return e.exit(e.InvalidUpstream, msg)
28 | end
29 |
30 | if t_upstream ~= nil then
31 | ngx.ctx.upstream = t_upstream
32 | end
33 |
34 | ngx.ctx.matched_policy = matched_policy
35 | ngx.ctx.alb_ctx.matched_policy = matched_policy
36 |
37 | if errmsg ~= nil then
38 | ngx_log(ngx.ERR, errmsg)
39 | e.exit(e.InvalidUpstream, errmsg)
40 | end
41 |
--------------------------------------------------------------------------------
/template/nginx/lua/metrics_auth.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 | local SKIP_METRICS_AUTH = os.getenv("METRICS_AUTH") == "false"
4 |
5 | local function get_token()
6 | local authorization = ngx.req.get_headers()['authorization']
7 | if type(authorization) ~= "string" then
8 | return nil
9 | end
10 | local matched = ngx.re.match(authorization, 'Bearer (.*)', 'jo')
11 |
12 | if matched == nil then
13 | return nil
14 | end
15 | local token = matched[1]
16 | if token == nil then
17 | return nil
18 | end
19 | return token
20 | end
21 |
22 | function _M.verify_auth()
23 | if SKIP_METRICS_AUTH then
24 | return
25 | end
26 | local token = get_token()
27 | if token == nil then
28 | ngx.status = 401
29 | ngx.say("Unauthorized")
30 | ngx.exit(401)
31 | end
32 | end
33 |
34 | return _M
35 |
--------------------------------------------------------------------------------
/template/nginx/lua/phase/balancer_phase.lua:
--------------------------------------------------------------------------------
1 | local balancer = require("balancer.balance")
2 | balancer.balance()
3 |
--------------------------------------------------------------------------------
/template/nginx/lua/phase/l7_header_filter_phase.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local e = require "error"
3 | local str = require "resty.string"
4 | local pm = require("plugins.core.plugin_manager")
5 |
6 | local matched_policy = ngx.ctx.matched_policy
7 | if matched_policy == nil then
8 | return
9 | end
10 | local cors = require "cors"
11 | local rewrite_header = require "rewrite_header"
12 |
13 | cors.header_filter()
14 | rewrite_header.rewrite_response_header()
15 | if ngx.ctx.is_alb_err then
16 | return
17 | end
18 |
19 | if ngx.ctx.alb_ctx.matched_policy then
20 | pm.response_header_filter_hook(ngx.ctx.alb_ctx)
21 | end
22 |
23 | local code = str.atoi(ngx.var.status)
24 | if code >= 400 then
25 | e.http_backend_error(code, "read " .. tostring(ngx.var.upstream_bytes_received) .. " byte data from backend")
26 | end
27 |
--------------------------------------------------------------------------------
/template/nginx/lua/phase/log_phase.lua:
--------------------------------------------------------------------------------
1 | -- format:on style:emmy
2 |
3 | local metrics = require("metrics")
4 | local pm = require("plugins.core.plugin_manager")
5 |
6 | -- request may jump to log phase directly (such like jumped via modsecurity)
7 | if not ngx.ctx.alb_ctx then
8 | return
9 | end
10 | metrics.log()
11 | if ngx.ctx.alb_ctx.matched_policy then
12 | pm.log_hook(ngx.ctx.alb_ctx)
13 | end
14 |
--------------------------------------------------------------------------------
/template/nginx/lua/phase/ssl_cert_phase.lua:
--------------------------------------------------------------------------------
1 | local c = require "cert_tool"
2 | c.select_cert()
3 |
--------------------------------------------------------------------------------
/template/nginx/lua/plugins/auth/auth.lua:
--------------------------------------------------------------------------------
1 | -- format:on style:emmy
2 |
3 | local cache = require("config.cache")
4 | local eh = require("error")
5 | local forward_auth = require("plugins.auth.forward_auth")
6 | local basic_auth = require("plugins.auth.basic_auth")
7 |
8 | local _m = {
9 | }
10 |
11 | ---@class AuthCtx
12 | ---@field auth_cookie? table the cookie from auth response
13 | ---@field always_set_cookie boolean
14 |
15 | ---@param ctx AlbCtx
16 | function _m.after_rule_match_hook(ctx)
17 | local auth_cfg, err = _m.get_config(ctx)
18 | if err ~= nil then
19 | eh.exit("get auth config fail", err)
20 | return
21 | end
22 | if auth_cfg == nil then
23 | return
24 | end
25 | forward_auth.do_forward_auth_if_need(auth_cfg, ctx)
26 | basic_auth.do_basic_auth_if_need(auth_cfg, ctx)
27 | end
28 |
29 | ---@param ctx AlbCtx
30 | function _m.response_header_filter_hook(ctx)
31 | if ctx.auth == nil then
32 | return
33 | end
34 | forward_auth.add_cookie_if_need(ctx)
35 | end
36 |
37 | ---@param ctx AlbCtx
38 | ---@return AuthPolicy?
39 | ---@return any? error
40 | function _m.get_config(ctx)
41 | return cache.get_config_from_policy(ctx.matched_policy, "auth")
42 | end
43 |
44 | return _m
45 |
--------------------------------------------------------------------------------
/template/nginx/lua/plugins/auth/buffer_md5.lua:
--------------------------------------------------------------------------------
1 | local ffi = require "ffi"
2 |
3 | local C = ffi.C
4 | local ffi_new = ffi.new
5 | local ffi_string = ffi.string
6 | local ngx = ngx
7 | local subsystem = ngx.config.subsystem
8 |
9 |
10 | local ngx_lua_ffi_md5_bin
11 | if subsystem == "http" then
12 | ffi.cdef [[
13 | void ngx_http_lua_ffi_md5_bin(const unsigned char *src, size_t len,
14 | unsigned char *dst);
15 | ]]
16 | ngx_lua_ffi_md5_bin = C.ngx_http_lua_ffi_md5_bin
17 | end
18 |
19 | local MD5_DIGEST_LEN = 16
20 | local md5_buf = ffi_new("unsigned char[?]", MD5_DIGEST_LEN)
21 |
22 | local _m = {}
23 |
24 | -- 17ms -> 14ms
25 | _m.md5_bin = function (sb)
26 | local ptr, len = sb:ref()
27 | ngx_lua_ffi_md5_bin(ptr, len, md5_buf)
28 | return ffi_string(md5_buf, MD5_DIGEST_LEN)
29 | end
30 |
31 | return _m
32 |
--------------------------------------------------------------------------------
/template/nginx/lua/plugins/otel/tool.lua:
--------------------------------------------------------------------------------
1 | local attr = require("opentelemetry.attribute")
2 |
3 | local _M = {}
4 | ---insert string attribute to table if val is not nil
5 | ---@param m table
6 | ---@param key string
7 | ---@param val? string
8 | function _M.attribute_set_string(m, key, val)
9 | if val == nil then
10 | return
11 | end
12 | table.insert(m, attr.string(key, val))
13 | end
14 |
15 | return _M
16 |
--------------------------------------------------------------------------------
/template/nginx/lua/plugins/timeout.lua:
--------------------------------------------------------------------------------
1 | local _m = {}
2 | local cache = require("config.cache")
3 | local json = require "cjson"
4 | local eh = require("error")
5 | local ngx_balancer = require "ngx.balancer"
6 |
7 | --- milliseconds to seconds,if ms is nil return nil
8 | --- @param ms number|nil
9 | ---@return number|nil
10 | local function ms2sec(ms)
11 | if ms == nil or ms == json.null then
12 | return nil
13 | end
14 | if ms <= 0 then
15 | return nil
16 | end
17 | return ms / 1000
18 | end
19 |
20 | ---@param ctx AlbCtx
21 | function _m.balancer_hook(ctx)
22 | local timeout_cfg, err = _m.get_config(ctx)
23 | if err ~= nil or timeout_cfg == nil then
24 | return
25 | end
26 |
27 | local connect = ms2sec(timeout_cfg.proxy_connect_timeout_ms)
28 | local send = ms2sec(timeout_cfg.proxy_send_timeout_ms)
29 | local read = ms2sec(timeout_cfg.proxy_read_timeout_ms)
30 | -- ngx.log(ngx.ERR, "[debug] set timeout ", connect, " ", send, " ", read)
31 | local _, err = ngx_balancer.set_timeouts(connect, send, read)
32 | if err ~= nil then
33 | eh.exit("set timeout fail", err)
34 | end
35 | end
36 |
37 | ---@param ctx AlbCtx
38 | ---@return TimeoutCr?
39 | ---@return any? error
40 | function _m.get_config(ctx)
41 | return cache.get_config_from_policy(ctx.matched_policy, "timeout")
42 | end
43 |
44 | return _m
45 |
--------------------------------------------------------------------------------
/template/nginx/lua/replace_prefix_match.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 | -- return the new url
4 | local sub = string.sub
5 | function _M.replace(url, prefix_match, replace_prefix)
6 | if sub(url, 1, #prefix_match) ~= prefix_match then
7 | -- ngx.log(ngx.ERR, "not match " .. url .. " " .. prefix_match)
8 | return url
9 | end
10 |
11 | local left = sub(url, #prefix_match + 1, #url)
12 | local prefix = replace_prefix
13 | local prefix_endwith_slash = sub(prefix, -1) == "/"
14 | local left_startwith_slash = sub(left, 1, 1) == "/"
15 |
16 | local sep = "/"
17 | if prefix_endwith_slash and left_startwith_slash then
18 | prefix = sub(prefix, 1, #prefix - 1)
19 | sep = ""
20 | end
21 | if prefix_endwith_slash or left_startwith_slash then
22 | sep = ""
23 | end
24 | if left == "" then
25 | sep = ""
26 | end
27 |
28 | -- ngx.log(ngx.ERR, "xx " .. prefix .. " | " .. sep .. " | " .. left)
29 | -- ngx.log(ngx.ERR, "xx " .. tostring(prefix_endwith_slash) .. " " .. tostring(left_startwith_slash))
30 | local new_url = prefix .. sep .. left
31 | if new_url == "" then
32 | return "/"
33 | end
34 | return new_url
35 | end
36 | return _M
37 |
--------------------------------------------------------------------------------
/template/nginx/lua/types/common.lua:
--------------------------------------------------------------------------------
1 | ---@alias var_string string a string may contain nginx variable
2 |
--------------------------------------------------------------------------------
/template/nginx/lua/types/vendor.lua:
--------------------------------------------------------------------------------
1 | ---@meta
2 | ---@class Tracer
3 | local Tracer = {}
4 |
5 | ---comment
6 | ---@param context any
7 | ---@param name string
8 | ---@param config any
9 | function Tracer:start(context, name, config) end
10 |
11 | local _ = Tracer
12 |
--------------------------------------------------------------------------------
/template/nginx/lua/utils/compress.lua:
--------------------------------------------------------------------------------
1 | ---@diagnostic disable: different-requires
2 | local _M = {}
3 | local zlib = require('lua-ffi-zlib.lib.ffi-zlib')
4 | -- decompress zlib format data from file
5 | -- arg fpath: string, path of the file
6 | -- ret out: string|nil,err: string| nil
7 | local _decompress_from_file = function(fpath)
8 | local f = io.open(fpath, "rb")
9 | if f == nil then
10 | return nil, "decompress file is nill"
11 | end
12 | local input = function(bufsize)
13 | local d = f:read(bufsize)
14 | if d == nil then
15 | return nil
16 | end
17 | return d
18 | end
19 | local out = {}
20 | local output = function(data)
21 | table.insert(out, data)
22 | end
23 | local ok, err = zlib.inflateGzip(input, output)
24 | if not ok then
25 | return nil,err
26 | end
27 | return table.concat(out),nil
28 | end
29 |
30 | -- decompress zlib format data from file
31 | -- arg fpath: string, path of the file
32 | -- ret out: string|nil,err: string| nil
33 | function _M.decompress_from_file(fpath)
34 | local ok,out,err = pcall(_decompress_from_file,fpath)
35 | if not ok then
36 | return nil,"decompress fail "..out
37 | end
38 | if err ~= nil then
39 | return nil,"decompress fail "..err
40 | end
41 | return out,nil
42 | end
43 |
44 | return _M
--------------------------------------------------------------------------------
/template/nginx/lua/utils/generic_ext.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 |
4 | --- nil_or return second if first is nil or empty string.
5 | -- @return string
6 | function _M.nil_or(first, second,empty)
7 | if first == nil then
8 | return second
9 | end
10 | if first == empty then
11 | return second
12 | end
13 | return first
14 | end
15 |
16 | return _M
--------------------------------------------------------------------------------
/template/nginx/lua/utils/numer_ext.lua:
--------------------------------------------------------------------------------
1 | local g_ext = require "utils.generic_ext"
2 |
3 | local _M = {}
4 |
5 | --- nil_or return second if first is nil or empty string.
6 | -- @return string
7 | function _M.nil_or(first, second)
8 | return g_ext.nil_or(first, second, 0)
9 | end
10 |
11 | return _M
12 |
--------------------------------------------------------------------------------
/template/nginx/lua/utils/subsystem.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local _M = {}
3 |
4 | local ngx_config = ngx.config
5 |
6 | local current_subsystem = ngx_config.subsystem
7 |
8 | local HTTP_SUBSYSTEM = "http"
9 | local STREAM_SUBSYSTEM = "stream"
10 |
11 | _M.CURRENT_SYBSYSTEM = current_subsystem
12 | _M.HTTP_SUBSYSTEM = HTTP_SUBSYSTEM
13 | _M.STREAM_SUBSYSTEM = STREAM_SUBSYSTEM
14 |
15 | ---@return boolean
16 | function _M.is_http_subsystem()
17 | return current_subsystem == HTTP_SUBSYSTEM
18 | end
19 |
20 | ---@return boolean
21 | function _M.is_stream_subsystem()
22 | return current_subsystem == STREAM_SUBSYSTEM
23 | end
24 |
25 | return _M
26 |
--------------------------------------------------------------------------------
/template/nginx/lua/vendor/lua-ffi-zlib/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Hamish Forbes
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 |
--------------------------------------------------------------------------------
/template/nginx/lua/vendor/lua-ffi-zlib/dist.ini:
--------------------------------------------------------------------------------
1 | name=lua-ffi-zlib
2 | abstract=Luajit FFI binding for zlib
3 | author=Hamish Forbes
4 | is_original=yes
5 | license=mit
6 | lib_dir=lib
7 | repo_link=https://github.com/hamishforbes/lua-ffi-zlib
8 | main_module=lib/ffi-zlib.lua
9 | requires = luajit
10 |
--------------------------------------------------------------------------------
/template/nginx/lua/vendor/lua-ffi-zlib/lua-ffi-zlib-0.4-0.rockspec:
--------------------------------------------------------------------------------
1 | package = "lua-ffi-zlib"
2 | version = "0.4-0"
3 | source = {
4 | url = "git://github.com/hamishforbes/lua-ffi-zlib",
5 | tag = "v0.4"
6 | }
7 | description = {
8 | summary = "A Lua module using LuaJIT's FFI feature to access zlib.",
9 | homepage = "https://github.com/hamishforbes/lua-ffi-zlib",
10 | maintainer = "Hamish Forbes"
11 | }
12 | dependencies = {
13 | "lua >= 5.1",
14 | }
15 | build = {
16 | type = "builtin",
17 | modules = {
18 | ["ffi-zlib"] = "lib/ffi-zlib.lua",
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/template/nginx/lua/vendor/lua-ffi-zlib/lua-ffi-zlib-0.5-0.rockspec:
--------------------------------------------------------------------------------
1 | package = "lua-ffi-zlib"
2 | version = "0.5-0"
3 | source = {
4 | url = "git://github.com/hamishforbes/lua-ffi-zlib",
5 | tag = "v0.5"
6 | }
7 | description = {
8 | summary = "A Lua module using LuaJIT's FFI feature to access zlib.",
9 | homepage = "https://github.com/hamishforbes/lua-ffi-zlib",
10 | maintainer = "Hamish Forbes"
11 | }
12 | dependencies = {
13 | "lua >= 5.1",
14 | }
15 | build = {
16 | type = "builtin",
17 | modules = {
18 | ["ffi-zlib"] = "lib/ffi-zlib.lua",
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/template/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | # a mini nginx.conf
2 | worker_processes 1;
3 |
4 | pid /etc/alb2/nginx/nginx.pid;
5 | error_log stderr notice;
6 |
7 | events {
8 | multi_accept on;
9 | worker_connections 51200;
10 | }
11 |
12 | http {}
13 |
--------------------------------------------------------------------------------
/template/nginx/policy.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "certificate_map": {
3 | "443": {
4 | "key": "",
5 | "cert": ""
6 | },
7 | "a.b.com": {
8 | "key": "",
9 | "cert": ""
10 | }
11 | },
12 | "stream": {
13 | "tcp": {
14 | "80": {
15 | "rule": "rule1",
16 | "upstream": "u1"
17 | }
18 | },
19 | "udp": {
20 | "80": {
21 | "rule": "rule2",
22 | "upstream": "u2"
23 | }
24 | }
25 | },
26 | "http": {
27 | "tcp": {
28 | "81": {
29 | "rule": "rule2",
30 | "upstream": "u2"
31 | }
32 | }
33 | },
34 | "backend_group": [
35 | {
36 | "name": "u1",
37 | "backends": [
38 | {
39 | "address": "127.0.0.1",
40 | "port": 9999,
41 | "weight": 100
42 | }
43 | ]
44 | },
45 | {
46 | "name": "u2",
47 | "backends": [
48 | {
49 | "address": "127.0.0.1",
50 | "port": 9999,
51 | "weight": 100
52 | }
53 | ]
54 | },
55 | {
56 | "name": "u3",
57 | "backends": [
58 | {
59 | "address": "127.0.0.1",
60 | "port": 9999,
61 | "weight": 100
62 | }
63 | ]
64 | }
65 | ]
66 | }
67 |
--------------------------------------------------------------------------------
/template/nginx/run-nginx.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [ -n "$TAIL_MODE" ]; then
4 | echo "tail mode wait forever"
5 | tail -f /dev/null
6 | fi
7 |
8 | umask 027
9 | mkdir -p /alb/nginx/run
10 | openssl dhparam -dsaparam -out /etc/alb2/nginx/dhparam.pem 2048
11 | cfg_path=$OLD_CONFIG_PATH
12 | if [ ! -f $cfg_path ]; then
13 | echo "copy init nginx.conf"
14 | cp /alb/nginx/nginx.conf $cfg_path
15 | cat $cfg_path
16 | fi
17 |
18 | nginx -g "daemon off;" -c /etc/alb2/nginx/nginx.conf -e /dev/stderr -p /alb/nginx/run
19 |
--------------------------------------------------------------------------------
/template/t/cors.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | our $policy = <<'_EOC_';
8 | {
9 | "certificate_map": {},
10 | "http": {"tcp": {"80": [
11 | {
12 | "rule": "",
13 | "internal_dsl": [
14 | [
15 | "STARTS_WITH",
16 | "URL",
17 | "/t"
18 | ]
19 | ],
20 | "enable_cors": true,
21 | "upstream": "test-upstream-1"
22 | }] }
23 | },
24 | "backend_group": [
25 | {
26 | "name": "test-upstream-1",
27 | "mode": "http",
28 | "backends": [
29 | {
30 | "address": "127.0.0.1",
31 | "port": 9999,
32 | "weight": 100
33 | }
34 | ]
35 | }
36 | ]
37 | }
38 | _EOC_
39 |
40 | log_level("info");
41 | no_shuffle();
42 | no_root_location();
43 | run_tests();
44 |
45 | __DATA__
46 |
47 | === TEST 1: http cors
48 | --- policy eval: $::policy
49 | --- lua_test
50 | local F = require("F");local u = require("util");local h = require("test-helper");
51 | local httpc = require("resty.http").new()
52 | local res, err = httpc:request_uri("http://127.0.0.1:80/t",{method="OPTIONS"})
53 | u.log(F"{u.inspect(res)}")
54 | h.assert_eq(res.status,204)
55 | h.assert_eq(res.headers["Access-Control-Allow-Origin"],"*")
--------------------------------------------------------------------------------
/template/t/e2e/auth_test/auth_test.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | my $ALB_BASE = $ENV{'TEST_BASE'};
8 |
9 | our $tt = t::Alauda::get_test_name(__FILE__);
10 |
11 | log_level("info");
12 | master_process_enabled("on");
13 | no_shuffle();
14 | no_root_location();
15 | run_tests();
16 |
17 | __DATA__
18 |
19 | === TEST 1: auth
20 | --- mock_backend eval: "1880 $::tt"
21 | --- lua_test_eval eval: "require('$::tt').test()"
22 |
--------------------------------------------------------------------------------
/template/t/e2e/cert/cert.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | my $base = $ENV{'TEST_BASE'};
8 | our $cert = <<_EOC_;
9 | $base/cert/tls.crt $base/cert/tls.key
10 | _EOC_
11 |
12 | our $http_config = <<_EOC_;
13 | server {
14 | listen 1880;
15 | location / {
16 | content_by_lua_block {
17 | require("e2e.cert.cert").as_backend(1880)
18 | }
19 | }
20 | }
21 | _EOC_
22 |
23 |
24 | log_level("info");
25 | workers(4);
26 | master_process_enabled("on");
27 | no_shuffle();
28 | no_root_location();
29 | run_tests();
30 |
31 | __DATA__
32 |
33 | === TEST 1: cert test
34 | --- certificate eval: $::cert
35 | --- http_config eval: $::http_config
36 | --- alb_https_port: 8443,9443
37 | --- disable_init_worker
38 | --- init_worker_eval: require("mock_worker_init").init_worker()
39 | --- timeout: 9999999
40 | --- lua_test_eval: require("e2e.cert.cert").test()
41 |
--------------------------------------------------------------------------------
/template/t/e2e/error_page/error.t:
--------------------------------------------------------------------------------
1 | use t::Alauda;
2 | use Test::Nginx::Socket 'no_plan';
3 | use Test::Nginx::Socket;
4 |
5 | our $http_config = <<_EOC_;
6 | server {
7 | listen 1880;
8 | location / {
9 | content_by_lua_block {
10 | require("e2e.error_page.error").as_backend(1880)
11 | }
12 | }
13 | }
14 | _EOC_
15 |
16 |
17 | log_level("info");
18 | master_process_enabled("on");
19 | no_shuffle();
20 | no_root_location();
21 | run_tests();
22 |
23 | __DATA__
24 |
25 | === TEST 1: error page test
26 | --- http_config eval: $::http_config
27 | --- timeout: 9999999
28 | --- lua_test_eval: require("e2e.error_page.error").test()
29 |
--------------------------------------------------------------------------------
/template/t/e2e/metrics/metrics.t:
--------------------------------------------------------------------------------
1 |
2 | use strict;
3 | use warnings;
4 | use t::Alauda;
5 | use Test::Nginx::Socket 'no_plan';
6 | use Test::Nginx::Socket;
7 |
8 | log_level("info");
9 | master_process_enabled("on");
10 | no_shuffle();
11 | # workers(4); # test for mutli metrics # currently mock init_worker has no way to sync backend in each worker..
12 | no_root_location();
13 | run_tests();
14 |
15 | __DATA__
16 |
17 | === TEST 1: clean-metrics
18 | --- mock_backend: 1880 e2e.metrics.metrics
19 | --- timeout: 9999999
20 | --- lua_test_eval: require("e2e.metrics.metrics").test()
21 |
--------------------------------------------------------------------------------
/template/t/e2e/ping/ping.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local _M = {}
3 | local h = require "test-helper"
4 | local u = require "util"
5 | local ph = require("policy_helper")
6 |
7 | function _M.as_backend()
8 | ngx.say "ok"
9 | end
10 |
11 | function _M.test()
12 | -- LuaFormatter off
13 | ph.set_policy_lua({
14 | http = {tcp = {["80"] = {
15 | {rule = "1", internal_dsl = {{"STARTS_WITH", "URL", "/t1"}}, upstream = "test-upstream-1"}}}
16 | },
17 | backend_group = {
18 | {name = "test-upstream-1", mode = "http", backends = {{address = "127.0.0.1", port = 1880, weight = 100}}}
19 | } }
20 | )
21 | -- LuaFormatter on
22 | local res = h.assert_curl("http://127.0.0.1:80/t1")
23 | u.logs(res)
24 | h.assert_eq(res.body, "ok\n")
25 | end
26 |
27 | return _M
28 |
--------------------------------------------------------------------------------
/template/t/e2e/ping/ping.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | log_level("info");
8 | master_process_enabled("on");
9 | no_shuffle();
10 | no_root_location();
11 | run_tests();
12 |
13 | __DATA__
14 |
15 | === TEST 1: ping
16 | --- mock_backend: 1880 e2e.ping.ping
17 | --- timeout: 9999999
18 | --- lua_test_eval: require("e2e.ping.ping").test()
19 |
--------------------------------------------------------------------------------
/template/t/e2e/retry_test/retry_test.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 | local F = require("F");
3 | local u = require("util");
4 | local h = require("test-helper");
5 | local httpc = require("resty.http").new();
6 |
7 | local function get_string_count(msg, module)
8 | local map = {
9 | ["http"] = "./template/servroot/logs/error.log",
10 | ["stream"] = "./template/servroot/logs/error.log",
11 | }
12 | local cmd = string.format([[bash -c "cat %s |grep '%s' | wc -l"]], map[module], msg)
13 | local final, err = u.shell(cmd)
14 | if err ~= nil and err ~= "" then
15 | h.fail("get string count fail")
16 | end
17 | return tonumber(final)
18 | end
19 |
20 | function _M.test()
21 | local msg = "connect() failed (111: Connection refused)"
22 | do
23 | local origin = get_string_count(msg, "http")
24 | local res, err = httpc:request_uri("http://127.0.0.1/ping")
25 | h.assert_eq(res.status, 502)
26 | local final = get_string_count(msg, "http")
27 | h.assert_eq(final - origin, 5, F("http {origin} {final}"))
28 | end
29 | do
30 | local origin = get_string_count(msg, "stream")
31 | local res, err = httpc:request_uri("http://127.0.0.1:81/ping")
32 | h.assert_eq(err, "connection reset by peer")
33 | local final = get_string_count(msg, "stream")
34 | h.assert_eq(final - origin, 5, F "stream {origin} {final}")
35 | end
36 | end
37 |
38 | return _M
39 |
--------------------------------------------------------------------------------
/template/t/e2e/rewrite_request/test.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | log_level("info");
8 | master_process_enabled("on");
9 | no_shuffle();
10 | no_root_location();
11 | run_tests();
12 |
13 | __DATA__
14 |
15 | === TEST 1: ping
16 | --- mock_backend: 1880 e2e.rewrite_request.test
17 | --- disable_init_worker
18 | --- init_worker_eval: require("mock_worker_init").init_worker()
19 | --- timeout: 9999999
20 | --- lua_test_eval: require("e2e.rewrite_request.test").test()
21 |
--------------------------------------------------------------------------------
/template/t/e2e/rule_match/rule.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local _M = {}
3 | local h = require "test-helper"
4 | local u = require "util"
5 | local ph = require("policy_helper")
6 |
7 | function _M.as_backend()
8 | ngx.say "ok"
9 | end
10 |
11 | function _M.test()
12 | -- LuaFormatter off
13 | ph.set_policy_lua({
14 | http = {
15 | tcp = {
16 | ["80"] = {
17 | { rule = "1", internal_dsl = { "AND", { "REGEX", "PARAM", "a", ".*" }, { "REGEX", "URL", "/t1.*" } }, upstream = "test-upstream-1" } }
18 | }
19 | },
20 | backend_group = {
21 | { name = "test-upstream-1", mode = "http", backends = { { address = "127.0.0.1", port = 1880, weight = 100 } } }
22 | }
23 | }
24 | )
25 | -- LuaFormatter on
26 | h.assert_curl("http://127.0.0.1:80/t1?v=v", {}, { status = 404 })
27 | end
28 |
29 | return _M
30 |
--------------------------------------------------------------------------------
/template/t/e2e/rule_match/rule.t:
--------------------------------------------------------------------------------
1 |
2 | use strict;
3 | use warnings;
4 | use t::Alauda;
5 | use Test::Nginx::Socket 'no_plan';
6 | use Test::Nginx::Socket;
7 |
8 | our $tt = t::Alauda::get_test_name(__FILE__);
9 |
10 | log_level("info");
11 | master_process_enabled("on");
12 | workers(1);
13 | worker_connections(51200);
14 | no_shuffle();
15 | no_root_location();
16 | run_tests();
17 |
18 | __DATA__
19 |
20 | === TEST 1: rule matches
21 | --- timeout: 30
22 | --- mock_backend eval: "1880 $::tt"
23 | --- init_worker_eval: require("mock_worker_init").init_worker()
24 | --- lua_test_eval eval: "require('$::tt').test()"
25 |
--------------------------------------------------------------------------------
/template/t/e2e/timeout_test/timeout_test.t:
--------------------------------------------------------------------------------
1 |
2 | use strict;
3 | use warnings;
4 | use t::Alauda;
5 | use Test::Nginx::Socket 'no_plan';
6 | use Test::Nginx::Socket;
7 |
8 | my $ALB_BASE = $ENV{'TEST_BASE'};
9 |
10 | our $tt = t::Alauda::get_test_name(__FILE__);
11 |
12 | log_level("info");
13 | master_process_enabled("on");
14 | no_shuffle();
15 | no_root_location();
16 | run_tests();
17 |
18 | __DATA__
19 |
20 | === TEST 1: timeout
21 | --- mock_backend eval: "1880 $::tt"
22 | --- lua_test_eval eval: "require('$::tt').test()"
23 |
24 | === TEST 2: timeout tcp
25 | --- mock_backend eval: "1880 $::tt"
26 | --- lua_test_stream_mode: "true"
27 | --- lua_test_eval eval: "require('$::tt').test()"
28 |
--------------------------------------------------------------------------------
/template/t/e2e/trace/trace.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 |
8 | our $http_config = <<_EOC_;
9 | server {
10 | listen 1880;
11 | location / {
12 | content_by_lua_block {
13 | require("e2e.trace.trace").as_backend(1880)
14 | }
15 | }
16 | }
17 | _EOC_
18 |
19 |
20 | log_level("info");
21 | master_process_enabled("on");
22 | no_shuffle();
23 | no_root_location();
24 | run_tests();
25 |
26 | __DATA__
27 |
28 | === TEST 1: trace test
29 | --- http_config eval: $::http_config
30 | --- timeout: 9999999
31 | --- lua_test_eval: require("e2e.trace.trace").test()
32 |
--------------------------------------------------------------------------------
/template/t/lib/mock_worker_init.lua:
--------------------------------------------------------------------------------
1 | -- format:on
2 | local M = {}
3 |
4 | local balancer = require("balancer.balance")
5 | local ph = require("config.policy_fetch")
6 | local cache = require("config.cache")
7 | local u = require("util")
8 | local subsys = require "utils.subsystem"
9 | local shm = require "config.shmap"
10 |
11 | function M.init_worker(_cfg)
12 | ngx.update_time()
13 | u.log("life: init worker " .. tostring(ngx.worker.id()))
14 | if subsys.is_http_subsystem() then
15 | cache.init_l7()
16 | else
17 | cache.init_l4()
18 | end
19 | local policy_raw, err = u.file_read_to_string(os.getenv("TEST_BASE") .. "/policy.new")
20 | if err ~= nil then
21 | ngx.exit(0)
22 | end
23 | ngx.update_time()
24 | shm.set_policy_raw("{}")
25 | ngx.update_time()
26 | ph.update_policy(policy_raw, "manual")
27 | ngx.update_time()
28 | u.log "life: update policy ok"
29 | balancer.sync_backends()
30 | ngx.update_time()
31 | u.log "life: sync backend ok"
32 | if subsys.is_http_subsystem() then
33 | ngx.update_time()
34 | require("metrics").init()
35 | ngx.update_time()
36 | u.log "life: init metrics ok"
37 | end
38 | end
39 |
40 | return M
41 |
--------------------------------------------------------------------------------
/template/t/lib/policy_helper.lua:
--------------------------------------------------------------------------------
1 | local common = require "utils.common"
2 | local p = require "config.policy_fetch"
3 | local balancer = require("balancer.balance")
4 | local M = {}
5 |
6 | function M.set_policy_json_str(policy)
7 | p.update_policy(policy, "manual")
8 | ngx.sleep(1)
9 | -- TODO it will only update cache for the current worker..
10 | balancer.sync_backends()
11 | end
12 |
13 | function M.set_policy_lua(policy_table)
14 | M.set_policy_json_str(common.json_encode(policy_table, true))
15 | end
16 |
17 | return M
18 |
--------------------------------------------------------------------------------
/template/t/manually/fortio/fortio.perf:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 |
8 | our $perf_case = "require(\"perf.e2e.fortio\").test(\"$ENV{PERF_CASE}\",\"$ENV{PERF_TIME}\")";
9 | our $perf_time = "$ENV{PERF_TIME}";
10 | warn "perf_case: $perf_case\n perf_time: $perf_time\n";
11 |
12 | log_level("info");
13 | master_process_enabled("on");
14 | workers(1);
15 | worker_connections(51200);
16 | no_shuffle();
17 | no_root_location();
18 | run_tests();
19 |
20 | __DATA__
21 |
22 | === TEST 1: perf
23 | --- init_worker_eval: require("mock_worker_init").init_worker()
24 | --- timeout eval: $::perf_time
25 | --- lua_test_eval eval: $::perf_case
26 |
--------------------------------------------------------------------------------
/template/t/manually/nyi/nyi:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | our $tt = t::Alauda::get_test_name(__FILE__);
8 |
9 | log_level("info");
10 | master_process_enabled("on");
11 | workers(1);
12 | worker_connections(51200);
13 | no_shuffle();
14 | no_root_location();
15 | run_tests();
16 |
17 | __DATA__
18 |
19 | === TEST 1: nyi
20 | --- timeout: 30
21 | --- enable_nyi
22 | --- init_worker_eval: require("mock_worker_init").init_worker()
23 | --- lua_test_eval eval: "require('$::tt').test()"
24 |
--------------------------------------------------------------------------------
/template/t/manually/nyi/nyi.lua:
--------------------------------------------------------------------------------
1 | local ph = require "policy_helper"
2 | local u = require "util"
3 | local h = require "test-helper"
4 | local _M = {}
5 |
6 | local function get_nyi_log()
7 | local cmd = string.format([[bash -c "cat %s |grep 'NYI' " ]], "./template/.nyi.log")
8 | local out, err = u.shell(cmd)
9 | if err ~= nil and err ~= "" then
10 | h.fail("get nyi log fail " .. err)
11 | end
12 | return out
13 | end
14 | function _M.test()
15 | ph.set_policy_lua({
16 | http = {
17 | tcp = {
18 | ["80"] = {
19 | { rule = "fortio", internal_dsl = { { "STARTS_WITH", "URL", "/" } }, upstream = "fortio" },
20 | }
21 | }
22 | },
23 | backend_group = {
24 | { name = "fortio", mode = "http", backends = { { address = "127.0.0.1", port = 8080, weight = 100 } } }
25 | },
26 | })
27 | u.logs("hello")
28 | local time = "30s"
29 | local cmd =
30 | "fortio load -a -labels 'u:nyi' -logger-force-color -c 8 -qps 30000 -nocatchup -uniform -t " ..
31 | time .. " 'http://127.0.0.1:80?size=1024:99'"
32 | local out, err = u.shell(cmd)
33 | u.logs("out", out, "err", err)
34 | u.log(get_nyi_log())
35 | end
36 |
37 | return _M
38 |
--------------------------------------------------------------------------------
/template/t/manually/otel_test/otel_test:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 | our $tt = t::Alauda::get_test_name(__FILE__);
8 |
9 | log_level("info");
10 | master_process_enabled("on");
11 | workers(1);
12 | worker_connections(51200);
13 | no_shuffle();
14 | no_root_location();
15 | run_tests();
16 |
17 | __DATA__
18 |
19 | === TEST 1: otel
20 | --- mock_backend eval: "1880 $::tt"
21 | --- timeout: 999999
22 | --- init_worker_eval: require("mock_worker_init").init_worker()
23 | --- lua_test_eval eval: "require('$::tt').test()"
24 |
--------------------------------------------------------------------------------
/template/t/nignx_config.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 |
6 | no_shuffle();
7 | no_root_location();
8 | run_tests();
9 |
10 | __DATA__
11 |
12 | === TEST 1: valid nginx config ok
13 | --- log_level: info
14 | --- alb_stream_server_config
15 | server {
16 | listen 9002 so_keepalive=on;
17 | content_by_lua_block {
18 | ngx.print("ok");
19 | }
20 | }
21 | server {
22 | listen 9001 so_keepalive=30m::10;
23 | content_by_lua_block {
24 | ngx.print("ok");
25 | }
26 | }
27 | server {
28 | listen 9003 so_keepalive=30m:1s:10;
29 | content_by_lua_block {
30 | ngx.print("ok");
31 | }
32 | }
33 | --- lua_test
34 | ngx.log(ngx.INFO, "ok")
35 |
--------------------------------------------------------------------------------
/template/t/resource/policy.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/template/t/resource/policy.bin
--------------------------------------------------------------------------------
/template/t/resource/policy.bin.empty:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/template/t/resource/policy.bin.empty
--------------------------------------------------------------------------------
/template/t/resource/policy.bin.invalid:
--------------------------------------------------------------------------------
1 | invalid
--------------------------------------------------------------------------------
/template/t/unit/common_test.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 | local t = require("test-helper");
4 | local u = require("util");
5 | local c = require("utils.common")
6 |
7 | function _M.test()
8 | u.logs("in common test")
9 | u.logs(c.json_decode('{"a":null}'))
10 | end
11 |
12 | return _M
13 |
--------------------------------------------------------------------------------
/template/t/unit/cors_test.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 | local h = require("test-helper");
4 | local cors = require("cors")
5 |
6 | function _M.test()
7 | h.assert_true(cors.origin_contains("http://a.com,http://b.com", "http://a.com"))
8 | h.assert_true(cors.origin_contains("http://a.com,http://b.com", "http://b.com"))
9 | h.assert_true(cors.origin_contains("http://a.com,http://b.com:123", "http://b.com:123"))
10 | h.assert_true(not cors.origin_contains("http://a.com:80,http://b.com:123", "http://a.com"))
11 | h.assert_true(not cors.origin_contains("http://a.com.cn,http://b.com", "http://a.com"))
12 | end
13 |
14 | return _M
15 |
--------------------------------------------------------------------------------
/template/t/unit/replace_prefix_match_test.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 | local F = require("F");
4 | local u = require("util")
5 | local h = require("test-helper");
6 | local r = require("replace_prefix_match")
7 |
8 | -- return the new url
9 | function _M.test()
10 | local cases = {
11 | {"/foo/bar", "/foo", "/xyz", "/xyz/bar"}, --
12 | {"/foo/bar", "/foo", "/xyz/", "/xyz/bar"}, --
13 | {"/foo/bar", "/foo/", "/xyz", "/xyz/bar"}, --
14 | {"/foo/bar", "/foo/", "/xyz/", "/xyz/bar"}, --
15 | {"/foo", "/foo", "/xyz", "/xyz"}, --
16 | {"/foo/", "/foo", "/xyz", "/xyz/"}, --
17 | {"/foo/bar", "/foo", "", "/bar"}, --
18 | {"/foo/", "/foo", "", "/"}, --
19 | {"/foo", "/foo", "", "/"}, --
20 | {"/foo/", "/foo", "/", "/"}, --
21 | {"/foo", "/foo", "/", "/"} --
22 | }
23 | local fail = false
24 | local msg = ""
25 | for k, c in pairs(cases) do
26 | h.P(F "case {k}")
27 | local url = c[1]
28 | local prefix_match = c[2]
29 | local replace_prefix = c[3]
30 | local expect_result = c[4]
31 | local result = r.replace(url, prefix_match, replace_prefix)
32 | if expect_result ~= result then
33 | h.P(F "fail {k} e {expect_result} r {result} " .. u.inspect(c))
34 | fail = true
35 | break
36 | end
37 | end
38 | if fail then
39 | h.P("fail ")
40 | h.fail()
41 | end
42 | end
43 | return _M
44 |
--------------------------------------------------------------------------------
/template/t/unit/unit_test.lua:
--------------------------------------------------------------------------------
1 | local _M = {}
2 |
3 | local u = require "util"
4 | local h = require("test-helper");
5 |
6 | function _M.test()
7 | u.logs("in unit test")
8 | local run_only = os.getenv("ALB_LUA_UNIT_TEST_CASE")
9 | if run_only and run_only ~= "" then
10 | u.logs("run only", run_only)
11 | require(run_only).test()
12 | return
13 | end
14 | require("unit.replace_prefix_match_test").test()
15 | require("unit.cert_test").test()
16 | require("unit.cors_test").test()
17 | require("unit.common_test").test()
18 | require("unit.plugins.auth.auth_unit_test").test()
19 | end
20 |
21 | return _M
22 |
--------------------------------------------------------------------------------
/template/t/unit/unit_test.t:
--------------------------------------------------------------------------------
1 | use strict;
2 | use warnings;
3 | use t::Alauda;
4 | use Test::Nginx::Socket 'no_plan';
5 | use Test::Nginx::Socket;
6 |
7 |
8 | log_level("info");
9 | no_shuffle();
10 | no_root_location();
11 | run_tests();
12 |
13 |
14 | __DATA__
15 |
16 | === TEST 1: unit tests
17 | --- http_config eval: ""
18 | --- disable_init_worker
19 | --- lua_test_eval: require("unit.unit_test").test()
20 |
21 |
22 |
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | 现在alb的代码中有三重测试方式
2 | ## unit test
3 | 测试代码放在源代码相同的package
4 | 一般用于测具体的函数.
5 | ## env test
6 | 测试代码放在test/e2e下,和unit test的区别是,env test使用会启动envtest并直接启动一个alb或者operator.
7 | 一般用于测alb和operator的行为
8 | ## kind test
9 | 测试代码放在test/kind下,和env test的区别是,kind test会使用kind部署一个k8s集群,并部署operator.
10 | 一般用于测试nginx相关的逻辑,和operator部署相关的逻辑.
11 |
--------------------------------------------------------------------------------
/test/alauda/README.md:
--------------------------------------------------------------------------------
1 | tests which hash testlink id and will generate allure report.
2 | which will do test in acp env.
--------------------------------------------------------------------------------
/test/checklist/hr.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: app.alauda.io/v1
2 | kind: HelmRequest
3 | metadata:
4 | annotations:
5 | cpaas.io/creator: admin
6 | generation: 1
7 | name: global-test
8 | namespace: cpaas-system
9 | spec:
10 | chart: stable/alauda-alb2
11 | clusterName: global
12 | namespace: cpaas-system
13 | values:
14 | address: 192.168.0.201
15 | displayName: ""
16 | enablePortProject: false
17 | LoadbalancerName: test
18 | nodeSelector:
19 | beta.kubernetes.io/os: linux
20 | projects:
21 | - ALL_ALL
22 | replicas: 1
23 | resources:
24 | limits:
25 | cpu: 200m
26 | memory: 256Mi
27 | requests:
28 | cpu: 200m
29 | memory: 256Mi
--------------------------------------------------------------------------------
/test/checklist/suite_test.go:
--------------------------------------------------------------------------------
1 | package checklist
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/onsi/ginkgo/v2"
7 | . "github.com/onsi/gomega"
8 | )
9 |
10 | func TestALBCheckList(t *testing.T) {
11 | RegisterFailHandler(Fail)
12 | RunSpecs(t, "alb checklist related test")
13 | }
14 |
--------------------------------------------------------------------------------
/test/conformance/ingress-nginx/README.md:
--------------------------------------------------------------------------------
1 | 这个目录下的测试的特殊之处在于我们可以用相同的测试函数来依次测试alb和ingress-nginx的行为.
2 |
--------------------------------------------------------------------------------
/test/conformance/ingress-nginx/lua_snip/app.lua:
--------------------------------------------------------------------------------
1 | local c = require("utils.common")
2 | if ngx.var.uri == "/ok" then
3 | ngx.say("ok")
4 | return
5 | end
6 | local id = ngx.var.http_id
7 | if id == nil then
8 | ngx.say("ok")
9 | return
10 | end
11 | ngx.log(ngx.INFO, "im app " .. id)
12 | local h, err = ngx.req.get_headers()
13 | if err ~= nil then
14 | ngx.log(ngx.ERR, "err: " .. tostring(err))
15 | end
16 | for k, v in pairs(h) do
17 | ngx.log(ngx.ERR, "app " .. tostring(k) .. " : " .. tostring(v))
18 | end
19 | if ngx.shared.state:get(id) == nil then
20 | ngx.shared.state:set(id, c.json_encode({}))
21 | end
22 |
23 | local data = c.json_decode(ngx.shared.state:get(id))
24 | data["/"] = h
25 | ngx.shared.state:set(id, c.json_encode(data))
26 |
27 | local data = c.json_decode(ngx.shared.state:get(id .. "-cfg"))
28 | for k, v in pairs(data.app_response_header) do
29 | ngx.header[k] = v
30 | end
31 | ngx.status = data.app_exit
32 | ngx.say(data.app_response_body)
33 | ngx.exit(data.app_exit)
34 | ngx.say("OK")
35 |
--------------------------------------------------------------------------------
/test/conformance/ingress-nginx/lua_snip/auth.lua:
--------------------------------------------------------------------------------
1 | local c = require("utils.common")
2 | ngx.log(ngx.INFO, "im auth")
3 | local id = ngx.var.http_id
4 | local h, err = ngx.req.get_headers()
5 | if err ~= nil then
6 | ngx.log(ngx.ERR, "err: " .. tostring(err))
7 | end
8 |
9 | if ngx.shared.state:get(id) == nil then
10 | local data = c.json_encode({}, true)
11 | ngx.log(ngx.ERR, "init state ", data, id)
12 | ngx.shared.state:set(id, data)
13 | end
14 |
15 | ngx.log(ngx.ERR, "state is " .. id .. " " .. tostring(ngx.shared.state:get(id)))
16 | local data = c.json_decode(ngx.shared.state:get(id))
17 | data["/auth"] = h
18 | ngx.shared.state:set(id, c.json_encode(data))
19 |
20 | for k, v in pairs(h) do
21 | ngx.log(ngx.ERR, "auth " .. tostring(k) .. " : " .. tostring(v))
22 | end
23 |
24 | local cfg = c.json_decode(ngx.shared.state:get(id .. "-cfg"))
25 | for k, v in pairs(cfg.auth_response_header) do
26 | ngx.header[k] = v
27 | end
28 |
29 | ngx.log(ngx.ERR, "auth exit with " .. tostring(cfg.auth_exit))
30 | ngx.status = cfg.auth_exit
31 | ngx.exit(cfg.auth_exit)
32 | ngx.say(cfg.auth_response_body)
33 |
--------------------------------------------------------------------------------
/test/conformance/ingress-nginx/lua_snip/state.lua:
--------------------------------------------------------------------------------
1 | ngx.req.read_body()
2 | ngx.log(ngx.INFO,
3 | "im state " .. ngx.var.http_id .. " " .. tostring(ngx.var.request_method) .. " " .. tostring(ngx.req.get_body_data()))
4 | local id = ngx.var.http_id
5 | local c = require("utils.common")
6 |
7 | if ngx.shared.state:get(id) == nil then
8 | ngx.shared.state:set(id, c.json_encode({}, true))
9 | end
10 |
11 | if ngx.var.request_method == "PUT" then
12 | ngx.shared.state:set(id .. "-cfg", ngx.req.get_body_data())
13 | ngx.say("OK")
14 | return
15 | end
16 | if ngx.var.request_method == "GET" then
17 | local out = ngx.shared.state:get(id) or "{}"
18 | ngx.log(ngx.INFO, "state is " .. id .. " " .. tostring(out))
19 | ngx.header["Content-Type"] = "application/json"
20 | ngx.say(out)
21 | end
22 |
--------------------------------------------------------------------------------
/test/conformance/ingress-nginx/suite_test.go:
--------------------------------------------------------------------------------
1 | package ingressnginx
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/onsi/ginkgo/v2"
7 | . "github.com/onsi/gomega"
8 | )
9 |
10 | // 在兼容ingress-nginx的情况下,用户常问的问题是,在xxx配置下,ingress-nginx 会是什么行为
11 | // conformance test 应该能够给出一个快速的有力的回应。
12 | // 同时,这下面的case 也是我们的e2e测试用例
13 | func TestIngressNginx(t *testing.T) {
14 | RegisterFailHandler(Fail)
15 | RunSpecs(t, "ingress nginx related e2e")
16 | }
17 |
--------------------------------------------------------------------------------
/test/e2e/framework/consts.go:
--------------------------------------------------------------------------------
1 | package framework
2 |
3 | var (
4 | DEFAULT_V4_IP_POOL = []string{"199.168.0.1"}
5 | DEFAULT_V6_IP_POOL = []string{"2004::199:168:128:235"}
6 | )
7 |
--------------------------------------------------------------------------------
/test/e2e/framework/suite_helper.go:
--------------------------------------------------------------------------------
1 | package framework
2 |
3 | import (
4 | "path"
5 | "runtime"
6 |
7 | . "alauda.io/alb2/utils/test_utils"
8 | "k8s.io/client-go/rest"
9 | )
10 |
11 | func AlbBeforeSuite(cfg *rest.Config) {
12 | _, filename, _, _ := runtime.Caller(0)
13 | albBase := path.Join(path.Dir(filename), "../../../")
14 | err := InitAlbCr(albBase, cfg)
15 | GinkgoNoErr(err)
16 | GinkgoNoErr(err)
17 | }
18 |
--------------------------------------------------------------------------------
/test/e2e/framework/tls.go:
--------------------------------------------------------------------------------
1 | package framework
2 |
3 | import (
4 | "context"
5 |
6 | . "alauda.io/alb2/utils/test_utils"
7 | corev1 "k8s.io/api/core/v1"
8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9 | )
10 |
11 | type TlsExt struct {
12 | Kc *K8sClient
13 | Ctx context.Context
14 | }
15 |
16 | func (t *TlsExt) CreateTlsSecret(domain, name, ns string) (*corev1.Secret, error) {
17 | key, crt, err := GenCert(domain)
18 | if err != nil {
19 | return nil, err
20 | }
21 | secret, err := t.Kc.GetK8sClient().CoreV1().Secrets(ns).Create(t.Ctx, &corev1.Secret{
22 | ObjectMeta: metav1.ObjectMeta{
23 | Name: name,
24 | Namespace: ns,
25 | },
26 | Data: map[string][]byte{
27 | "tls.key": []byte(key),
28 | "tls.crt": []byte(crt),
29 | },
30 | Type: corev1.SecretTypeTLS,
31 | }, metav1.CreateOptions{})
32 | if err != nil {
33 | return nil, err
34 | }
35 | return secret, nil
36 | }
37 |
--------------------------------------------------------------------------------
/test/e2e/operator/README.md:
--------------------------------------------------------------------------------
1 | 这个package主要测试operator部署相关的东西
2 |
3 | matrix
4 | | gateway:| enable-shared | enable-standalone | disable|
5 | |--------|---------------|----------------------------|
6 | | network:| host | container |
7 | |--------|---------------|----------------------------|
8 | | alb: | enable | disable |
9 |
10 | 3 * 2 * 2 = 12
11 | gateway disable and alb disable is meaningless. left 11
12 | ## common used mode
13 | ### 1. global default 集群默认部署的alb
14 | gateway enable-shared
15 | network host
16 | alb enable
17 | ### 2. user deploy alb-host 用户部署的主机网络的alb
18 | gateway disable
19 | network host
20 | alb enable
21 | ### 3. user deploy alb-container 用户部署的容器网络的alb
22 | gateway disable
23 | network container
24 | alb enable
25 | ### 4. user deploy gateway 3.14之后加入的 独享型gateway
26 | gateway enable-standalone
27 | network container
28 | alb disable
29 | ### 5. user deploy gateway (with alb)
30 | gateway enable-standalone
31 | network container
32 | alb enable
--------------------------------------------------------------------------------
/test/e2e/rule-perf-cpu:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alauda/alb/314b8a693f1d84a3a5f561b846f7e1cef61bfb5c/test/e2e/rule-perf-cpu
--------------------------------------------------------------------------------
/test/e2e/suite_test.go:
--------------------------------------------------------------------------------
1 | package simple
2 |
3 | import (
4 | "testing"
5 |
6 | _ "alauda.io/alb2/test/e2e/alb"
7 | _ "alauda.io/alb2/test/e2e/cases"
8 | _ "alauda.io/alb2/test/e2e/gateway"
9 | _ "alauda.io/alb2/test/e2e/ingress"
10 | _ "alauda.io/alb2/test/e2e/operator/alb"
11 | _ "alauda.io/alb2/test/e2e/operator/gateway"
12 | _ "alauda.io/alb2/test/e2e/operator/public-cloud"
13 | _ "alauda.io/alb2/test/e2e/operator/rawk8s"
14 | _ "alauda.io/alb2/test/e2e/operator/simple"
15 | _ "alauda.io/alb2/test/e2e/perf"
16 | . "github.com/onsi/ginkgo/v2"
17 | . "github.com/onsi/gomega"
18 | )
19 |
20 | func TestALB(t *testing.T) {
21 | RegisterFailHandler(Fail)
22 | RunSpecs(t, "alb operator related e2e")
23 | }
24 |
--------------------------------------------------------------------------------
/test/kind/e2e/suite_test.go:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/onsi/ginkgo/v2"
7 | . "github.com/onsi/gomega"
8 |
9 | _ "alauda.io/alb2/test/kind/e2e/gateway"
10 | _ "alauda.io/alb2/test/kind/e2e/operator"
11 | )
12 |
13 | func TestAlbKindE2e(t *testing.T) {
14 | RegisterFailHandler(Fail)
15 | RunSpecs(t, "Kind e2e Suite")
16 | }
17 |
--------------------------------------------------------------------------------
/test/kind/pkg/helper/alb-chart-ext_test.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "testing"
5 |
6 | "alauda.io/alb2/utils/log"
7 | . "alauda.io/alb2/utils/test_utils"
8 | "github.com/stretchr/testify/assert"
9 | "github.com/ztrue/tracerr"
10 | )
11 |
12 | func TestChart(t *testing.T) {
13 | base := InitBase()
14 | l := log.L()
15 | {
16 | chart := "registry.alauda.cn:60080/acp/chart-alauda-alb2:v3.13.0-alpha.11"
17 | ac, err := LoadAlbChartFromUrl(base, NewHelm(base, nil, l), chart, l)
18 | tracerr.Print(err)
19 | assert.NoError(t, err)
20 | imgs, err := ac.ListImage()
21 | assert.NoError(t, err)
22 | l.Info("imgs", "img", imgs)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/test/kind/pkg/helper/king-gc_test.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | "time"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestIsNeedGcKind(t *testing.T) {
12 | type TestCase struct {
13 | prefix string
14 | time int64
15 | need bool
16 | }
17 | now := time.Now().Unix()
18 | new2h := time.Now().Add(time.Hour * 2).Unix()
19 | old2h := time.Now().Add(time.Hour * -2).Unix()
20 | cases := []TestCase{
21 | {
22 | prefix: "xx-ddd",
23 | time: now,
24 | need: false,
25 | },
26 | {
27 | prefix: "xx-ddd",
28 | time: new2h,
29 | need: false,
30 | },
31 | {
32 | prefix: "xx-ddd",
33 | time: old2h,
34 | need: true,
35 | },
36 | }
37 | for _, c := range cases {
38 | need, _ := isNeedGC(fmt.Sprintf("%s-%d", c.prefix, c.time))
39 | assert.Equal(t, need, c.need)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/test/kind/pkg/helper/qps/assert.go:
--------------------------------------------------------------------------------
1 | package qps
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type QpsSummaryAssert struct {
8 | summary []History
9 | }
10 |
11 | func NewSummaryAssert(sum []History) *QpsSummaryAssert {
12 | return &QpsSummaryAssert{summary: sum}
13 | }
14 |
15 | func (s *QpsSummaryAssert) NoError() {
16 | for _, s := range s.summary {
17 | for _, r := range s.records {
18 | if r.code != 200 {
19 | panic(fmt.Errorf("find a err %v", r))
20 | }
21 | }
22 | }
23 | }
24 |
25 | func (s *QpsSummaryAssert) QpsAbove(qps int) {
26 | for _, s := range s.summary {
27 | // qps := s.success / uint64(s.dur)
28 | cur := s.success / uint64(s.dur)
29 | if cur < uint64(qps) {
30 | panic(fmt.Errorf("qps expect >%d but is %d ", qps, cur))
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/test/kind/pkg/helper/qps/curl.go:
--------------------------------------------------------------------------------
1 | package qps
2 |
3 | import (
4 | "io/ioutil"
5 | "net/http"
6 | )
7 |
8 | func Curl(url string) (string, error) {
9 | c := http.Client{}
10 | req, err := http.NewRequest("GET", url, nil)
11 | if err != nil {
12 | return "", err
13 | }
14 | resp, err := c.Do(req)
15 | if err != nil {
16 | return "", err
17 | }
18 | defer resp.Body.Close()
19 | body, err := ioutil.ReadAll(resp.Body)
20 | if err != nil {
21 | return "", err
22 | }
23 | return string(body), nil
24 | }
25 |
--------------------------------------------------------------------------------
/test/kind/pkg/helper/qps/keep-curl_test.go:
--------------------------------------------------------------------------------
1 | package qps
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "io"
7 | "net/http"
8 | "testing"
9 | "time"
10 |
11 | . "alauda.io/alb2/utils/log"
12 | . "alauda.io/alb2/utils/test_utils"
13 | )
14 |
15 | func TestQps(t *testing.T) {
16 | l := L()
17 | l.Info("ok")
18 | ctx, cancel := CtxWithSignalAndTimeout(5 * 60)
19 | go func() {
20 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
21 | io.WriteString(w, "hello world")
22 | })
23 | http.ListenAndServe(":8090", nil)
24 | }()
25 | defer cancel()
26 | tctx, xcancel := context.WithTimeout(ctx, time.Second*30)
27 | defer xcancel()
28 | r := NewReqProvider("http://localhost:8090", l, tctx)
29 | r.WithSampleInterval(3)
30 | r.Start()
31 | fmt.Printf("test ok")
32 | s := NewSummaryAssert(r.Summary())
33 | s.NoError()
34 | s.QpsAbove(300)
35 | }
36 |
--------------------------------------------------------------------------------
/timestamp.txt:
--------------------------------------------------------------------------------
1 | Fri, 16 Jun 2023 19:52:57 +0800
2 |
--------------------------------------------------------------------------------
/utils/address.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "net/url"
5 | "strings"
6 | )
7 |
8 | func ParseAddressStr(address string) (ip []string, host []string) {
9 | return ParseAddressList(SplitAndRemoveEmpty(address, ","))
10 | }
11 |
12 | func ParseAddressList(addrs []string) (ip []string, host []string) {
13 | ip = []string{}
14 | host = []string{}
15 | for _, addr := range addrs {
16 | addr = strings.TrimSpace(addr)
17 | if addr == "" {
18 | continue
19 | }
20 | v4, v6, hostname, err := addressIs(addr)
21 | if err != nil {
22 | continue
23 | }
24 | if v4 || v6 {
25 | ip = append(ip, addr)
26 | }
27 | if hostname {
28 | host = append(host, addr)
29 | }
30 | }
31 | return ip, host
32 | }
33 |
34 | func addressIs(address string) (ipv4 bool, ipv6 bool, domain bool, err error) {
35 | if IsValidIPv4(address) {
36 | return true, false, false, nil
37 | }
38 | if IsValidIPv6(address) {
39 | return false, true, false, nil
40 | }
41 | _, err = url.Parse(address)
42 | if err != nil {
43 | return false, false, false, err
44 | }
45 | return false, false, true, nil
46 | }
47 |
--------------------------------------------------------------------------------
/utils/consts.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | const (
4 | OP_AND = "AND"
5 | OP_EXIST = "EXIST"
6 | OP_EQ = "EQ"
7 | OP_IN = "IN"
8 | OP_OR = "OR"
9 | OP_RANGE = "RANGE"
10 | OP_REGEX = "REGEX"
11 | OP_STARTS_WITH = "STARTS_WITH"
12 | OP_ENDS_WITH = "ENDS_WITH"
13 |
14 | KEY_HOST = "HOST"
15 | KEY_URL = "URL"
16 | KEY_SRC_IP = "SRC_IP"
17 | KEY_HEADER = "HEADER"
18 | KEY_COOKIE = "COOKIE"
19 | KEY_PARAM = "PARAM"
20 | KEY_METHOD = "METHOD"
21 | )
22 |
--------------------------------------------------------------------------------
/utils/dirhash/hash_test.go:
--------------------------------------------------------------------------------
1 | // Copy from https://github.com/golang/mod/blob/master/sumdb/dirhash/hash.go
2 | package dirhash
3 |
4 | import (
5 | "crypto/sha256"
6 | "encoding/base32"
7 | "strings"
8 | "testing"
9 |
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | func TestLabelSafeHash(t *testing.T) {
14 | origin := "a" + strings.Repeat("b", 1000)
15 | h := sha256.New()
16 | h.Write([]byte(origin))
17 | sha256Result := h.Sum(nil)
18 | str := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(sha256Result)
19 | t.Logf("str %s %v", str, len(str))
20 | assert.Equal(t, true, len(str) == 52)
21 | }
22 |
--------------------------------------------------------------------------------
/utils/log/log_test.go:
--------------------------------------------------------------------------------
1 | package log
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestLog(_ *testing.T) {
8 | l := L()
9 | l.V(-100).Info("test v-100")
10 | l.V(-3).Info("test v-3")
11 | l.V(-2).Info("test v-2")
12 | l.V(-1).Info("test v-1")
13 | l.V(0).Info("test v0")
14 | l.V(1).Info("test v1")
15 | l.V(2).Info("test v2")
16 | l.V(3).Info("test v3")
17 | l.V(4).Info("test v4")
18 | l.V(5).Info("test v5")
19 |
20 | l.Info("test tagged", "a", "b")
21 | l.WithName("name1").Info("test with name", "a", "b")
22 | l.WithName("name1").WithName("name2").Info("test with name", "a", "b")
23 |
24 | {
25 | l := InitKlogV2(LogCfg{ToFile: "./test.log"})
26 | l.Info("test other log")
27 | Flush()
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/utils/net_utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "net"
5 | "strings"
6 | )
7 |
8 | func IsIPv4(address string) bool {
9 | return strings.Count(address, ":") < 2
10 | }
11 |
12 | func IsValidIPv4(address string) bool {
13 | if !IsIPv4(address) {
14 | return false
15 | }
16 | return net.ParseIP(address) != nil
17 | }
18 |
19 | func IsIPv6(address string) bool {
20 | return strings.Count(address, ":") >= 2
21 | }
22 |
23 | func IsValidIPv6(address string) bool {
24 | if !IsIPv6(address) {
25 | return false
26 | }
27 | return net.ParseIP(address) != nil
28 | }
29 |
30 | func IsIPv6Link(address string) bool {
31 | return strings.Count(address, ":") >= 2 && strings.HasPrefix(address, "fe80")
32 | }
33 |
--------------------------------------------------------------------------------
/utils/string_ext.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "strings"
5 |
6 | "github.com/samber/lo"
7 | )
8 |
9 | func StrIsNillOrEq(left *string, right string) bool {
10 | return left == nil || (left != nil && *left == right)
11 | }
12 |
13 | func StrListRemoveDuplicates(list []string) []string {
14 | m := make(map[string]string)
15 | for _, x := range list {
16 | m[x] = x
17 | }
18 | var ClearedArr []string
19 | for x := range m {
20 | ClearedArr = append(ClearedArr, x)
21 | }
22 | return ClearedArr
23 | }
24 |
25 | func SplitAndRemoveEmpty(s string, sep string) []string {
26 | items := strings.Split(s, sep)
27 | return lo.Filter(items, func(s string, _ int) bool { return strings.TrimSpace(s) != "" })
28 | }
29 |
--------------------------------------------------------------------------------
/utils/string_ext_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "strings"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestStringSplit(t *testing.T) {
11 | assert.Equal(t, strings.Split("", ","), []string{""})
12 | assert.Equal(t, SplitAndRemoveEmpty("", ","), []string{})
13 | }
14 |
--------------------------------------------------------------------------------
/utils/test_utils/assert/alb.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "context"
5 |
6 | a2t "alauda.io/alb2/pkg/apis/alauda/v2beta1"
7 | "github.com/go-logr/logr"
8 | "k8s.io/apimachinery/pkg/api/errors"
9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10 |
11 | . "alauda.io/alb2/utils/test_utils"
12 | )
13 |
14 | func WaitAlbReady(cli *K8sClient, log logr.Logger, ctx context.Context, ns string, name string) *a2t.ALB2 {
15 | return WaitAlbState(cli, log, ctx, ns, name, func(alb *a2t.ALB2) (bool, error) {
16 | return alb.Status.State == a2t.ALB2StateRunning, nil
17 | })
18 | }
19 |
20 | func WaitAlbState(cli *K8sClient, log logr.Logger, ctx context.Context, ns string, name string, check func(alb *a2t.ALB2) (bool, error)) *a2t.ALB2 {
21 | var globalAlb *a2t.ALB2
22 | Wait(func() (bool, error) {
23 | alb, err := cli.GetAlbClient().CrdV2beta1().ALB2s(ns).Get(context.Background(), name, metav1.GetOptions{})
24 | log.Info("try get alb ", "ns", ns, "name", name)
25 | if errors.IsNotFound(err) {
26 | return false, nil
27 | }
28 | if err != nil {
29 | return false, err
30 | }
31 | ok, err := check(alb)
32 | if err == nil {
33 | globalAlb = alb
34 | return ok, nil
35 | }
36 | return ok, err
37 | })
38 | return globalAlb
39 | }
40 |
--------------------------------------------------------------------------------
/utils/test_utils/assert/deployment.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | "context"
5 | "time"
6 |
7 | . "alauda.io/alb2/utils/test_utils"
8 | "github.com/go-logr/logr"
9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10 | )
11 |
12 | type DeploymentAssert struct {
13 | kc *K8sClient
14 | log logr.Logger
15 | }
16 |
17 | func NewDeploymentAssert(kc *K8sClient, log logr.Logger) *DeploymentAssert {
18 | return &DeploymentAssert{
19 | kc: kc,
20 | log: log,
21 | }
22 | }
23 |
24 | func (d *DeploymentAssert) WaitReady(ctx context.Context, name string, ns string) {
25 | cli := d.kc.GetK8sClient().AppsV1().Deployments(ns)
26 | for {
27 | time.Sleep(time.Second * 1)
28 | depl, err := cli.Get(ctx, name, metav1.GetOptions{})
29 | if err != nil {
30 | d.log.Error(err, "get deployment", "name", name, "ns", ns)
31 | continue
32 | }
33 |
34 | if depl.Status.AvailableReplicas != *depl.Spec.Replicas {
35 | d.log.Info("deployment not ready", "depl", PrettyCr(depl))
36 | continue
37 | }
38 | return
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/utils/test_utils/assert/ingress.go:
--------------------------------------------------------------------------------
1 | package assert
2 |
3 | import (
4 | mapset "github.com/deckarep/golang-set/v2"
5 | "github.com/samber/lo"
6 | n1 "k8s.io/api/networking/v1"
7 | )
8 |
9 | type IngressAssert struct {
10 | ing *n1.Ingress
11 | }
12 |
13 | func NewIngressAssert(ing *n1.Ingress) *IngressAssert {
14 | return &IngressAssert{
15 | ing: ing,
16 | }
17 | }
18 |
19 | func (i *IngressAssert) HasLoadBalancerIP(ip string) bool {
20 | for _, lb := range i.ing.Status.LoadBalancer.Ingress {
21 | if lb.IP == ip {
22 | return true
23 | }
24 | }
25 | return false
26 | }
27 |
28 | func (i *IngressAssert) HasLoadBalancerHost(host string) bool {
29 | for _, lb := range i.ing.Status.LoadBalancer.Ingress {
30 | if lb.Hostname == host {
31 | return true
32 | }
33 | }
34 | return false
35 | }
36 |
37 | func (i *IngressAssert) HasLoadBalancerHostAndPort(host string, port []int32) bool {
38 | pmap := mapset.NewSet(port...)
39 | for _, lb := range i.ing.Status.LoadBalancer.Ingress {
40 | if lb.Hostname != host {
41 | continue
42 | }
43 | ports := mapset.NewSet(lo.Map(lb.Ports, func(p n1.IngressPortStatus, _ int) int32 {
44 | return p.Port
45 | })...)
46 | if ports.IsSuperset(pmap) {
47 | return true
48 | }
49 | }
50 | return false
51 | }
52 |
--------------------------------------------------------------------------------
/utils/test_utils/console_logger.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/go-logr/logr"
7 | )
8 |
9 | type ConsoleLogSink struct {
10 | prefix string
11 | }
12 |
13 | func ConsoleLog() logr.Logger {
14 | return logr.New(ConsoleLogSink{})
15 | }
16 |
17 | func (l ConsoleLogSink) Init(logr.RuntimeInfo) {
18 | }
19 |
20 | func (l ConsoleLogSink) Enabled(int) bool {
21 | return true
22 | }
23 |
24 | func (l ConsoleLogSink) log(msg string) {
25 | fmt.Println(msg)
26 | }
27 |
28 | func (l ConsoleLogSink) Info(level int, msg string, kv ...interface{}) {
29 | l.log(fmt.Sprintf("%s level %d %s %s %v ", nowStamp(), level, l.prefix, msg, kv))
30 | }
31 |
32 | func (l ConsoleLogSink) Error(err error, msg string, kv ...interface{}) {
33 | l.log(fmt.Sprintf("%s err %v %s %s %v ", nowStamp(), err, l.prefix, msg, kv))
34 | }
35 |
36 | func (l ConsoleLogSink) WithValues(kv ...interface{}) logr.LogSink {
37 | return ConsoleLogSink{prefix: fmt.Sprintf("%s %v", l.prefix, kv)}
38 | }
39 |
40 | func (l ConsoleLogSink) WithName(msg string) logr.LogSink {
41 | return ConsoleLogSink{prefix: fmt.Sprintf("%s %v", l.prefix, msg)}
42 | }
43 |
--------------------------------------------------------------------------------
/utils/test_utils/docker-ext_test.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestDockerHasImage(t *testing.T) {
8 | d := NewDockerExt(ConsoleLog())
9 | has, err := d.HasImage("registry.alauda.cn:60080/acp/alb2:local")
10 | t.Logf("%v %v", has, err)
11 | }
12 |
--------------------------------------------------------------------------------
/utils/test_utils/eq.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "reflect"
5 | "sort"
6 | )
7 |
8 | func StringsEq(left, right []string) bool {
9 | if len(left) != len(right) {
10 | return false
11 | }
12 | sort.Strings(left)
13 | sort.Strings(right)
14 | return reflect.DeepEqual(left, right)
15 | }
16 |
--------------------------------------------------------------------------------
/utils/test_utils/ginkgo_ext.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/go-logr/logr"
7 | "github.com/onsi/gomega"
8 | )
9 |
10 | func nowStamp() string {
11 | return time.Now().Format(time.StampMilli)
12 | }
13 |
14 | func EventuallySuccess(f func(g gomega.Gomega), log logr.Logger) {
15 | gomega.Eventually(func(g gomega.Gomega) {
16 | log.Info("check")
17 | f(g)
18 | }, "10m", "2s").Should(gomega.Succeed(), func(message string, callerSkip ...int) {
19 | })
20 | }
21 |
22 | func GNoErr(g gomega.Gomega, err error) {
23 | g.Expect(err).ShouldNot(gomega.HaveOccurred())
24 | }
25 |
26 | func GEqual(g gomega.Gomega, left interface{}, right interface{}) {
27 | g.Expect(left).Should(gomega.Equal(right))
28 | }
29 |
--------------------------------------------------------------------------------
/utils/test_utils/ginkgo_logger.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/go-logr/logr"
7 | "github.com/onsi/ginkgo/v2"
8 | )
9 |
10 | type GinkgoLogSink struct {
11 | prefix string
12 | }
13 |
14 | // Deprecated
15 | // 字符串中含有%时, %v的处理是错的..
16 | func GinkgoLog() logr.Logger {
17 | return logr.New(GinkgoLogSink{})
18 | }
19 |
20 | func (l GinkgoLogSink) Init(logr.RuntimeInfo) {
21 | }
22 |
23 | func (l GinkgoLogSink) Enabled(int) bool {
24 | return true
25 | }
26 |
27 | func (l GinkgoLogSink) log(msg string) {
28 | fmt.Fprintf(ginkgo.GinkgoWriter, msg+"\n")
29 | }
30 |
31 | func (l GinkgoLogSink) Info(level int, msg string, kv ...interface{}) {
32 | l.log(fmt.Sprintf("%s level %d %s %s %v", nowStamp(), level, l.prefix, msg, kv))
33 | }
34 |
35 | func (l GinkgoLogSink) Error(err error, msg string, kv ...interface{}) {
36 | l.log(fmt.Sprintf("%s err %v %s %s %v ", nowStamp(), err, l.prefix, msg, kv))
37 | }
38 |
39 | func (l GinkgoLogSink) WithValues(kv ...interface{}) logr.LogSink {
40 | return GinkgoLogSink{prefix: fmt.Sprintf("%s %v", l.prefix, kv)}
41 | }
42 |
43 | func (l GinkgoLogSink) WithName(msg string) logr.LogSink {
44 | return GinkgoLogSink{prefix: fmt.Sprintf("%s %v", l.prefix, msg)}
45 | }
46 |
--------------------------------------------------------------------------------
/utils/test_utils/json.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import "github.com/wI2L/jsondiff"
4 |
5 | func JsonBelongsTO(left, right interface{}) (bool, interface{}, error) {
6 | patch, err := jsondiff.Compare(left, right)
7 | if err != nil {
8 | return false, nil, err
9 | }
10 | for _, v := range patch {
11 | if v.Type != "remove" {
12 | return false, patch, nil
13 | }
14 | }
15 | return true, patch, nil
16 | }
17 |
--------------------------------------------------------------------------------
/utils/test_utils/kind-ext_test.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "testing"
5 |
6 | "alauda.io/alb2/utils/log"
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestGetConfig(t *testing.T) {
11 | t.Skip("dev")
12 | c := KindConfig{
13 | Name: "alb-dual",
14 | Image: "kindest/node:v1.24.3",
15 | ClusterYaml: `
16 | kind: Cluster
17 | apiVersion: kind.x-k8s.io/v1alpha4
18 | networking:
19 | ipFamily: dual
20 | apiServerAddress: "127.0.0.1"
21 | nodes:
22 | - role: control-plane
23 | - role: worker
24 | - role: worker
25 | `,
26 | }
27 | l := log.L()
28 |
29 | base := InitBase()
30 | kd, err := DeployOrAdopt(c, base, "alb-dual", l)
31 | assert.NoError(t, err)
32 | cfg, err := kd.GetConfig()
33 | assert.NoError(t, err)
34 | k := NewKubectl(base, cfg, l)
35 | out, err := k.Kubectl("get", "nodes")
36 | t.Log(out)
37 | assert.NoError(t, err)
38 | }
39 |
--------------------------------------------------------------------------------
/utils/test_utils/util_test.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/stretchr/testify/assert"
7 | )
8 |
9 | func TestGenCert(t *testing.T) {
10 | key, cert, err := GenCert("a.b.c")
11 | assert.NoError(t, err)
12 | t.Logf("key %s", key)
13 | t.Logf("cert %s ", cert)
14 | }
15 |
16 | func TestTemplate(t *testing.T) {
17 | ts := `
18 | a: {{.Values.x}}
19 | {{- if eq .Values.b "true" }}
20 | b: 1
21 | {{- end}}
22 | {{- if .Values.c }}
23 | c: 1
24 | {{- end}}
25 | `
26 | out := Template(ts, map[string]interface{}{
27 | "Values": map[string]interface{}{
28 | "x": "1",
29 | "b": "false",
30 | "c": true,
31 | },
32 | })
33 | assert.Equal(t, out, `
34 | a: 1
35 | c: 1
36 | `)
37 | t.Log(out)
38 | }
39 |
--------------------------------------------------------------------------------
/utils/test_utils/yq.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "os/exec"
7 | "strings"
8 | )
9 |
10 | type Yq struct {
11 | Base string
12 | }
13 |
14 | func YqDo(raw string, cmd string) (string, error) {
15 | // only use for test
16 | raw = strings.TrimSpace(raw)
17 | base, err := os.MkdirTemp("", "yq")
18 | if err != nil {
19 | return "", err
20 | }
21 | p := base + "/" + "x.yaml"
22 | err = os.WriteFile(p, []byte(raw), 0o666)
23 | if err != nil {
24 | return "", err
25 | }
26 | sh := fmt.Sprintf(`#!/bin/bash
27 | cat %s | %s
28 | `, p, cmd)
29 | os.WriteFile(base+"/x.sh", []byte(sh), 0o666)
30 | sh_p := base + "/x.sh"
31 | out, err := exec.Command("bash", sh_p).CombinedOutput()
32 | if err != nil {
33 | return "", fmt.Errorf("eval %s fail %v", sh_p, err)
34 | }
35 | return strings.TrimSpace(string(out)), nil
36 | }
37 |
--------------------------------------------------------------------------------
/utils/test_utils/yq_test.go:
--------------------------------------------------------------------------------
1 | package test_utils
2 |
3 | import (
4 | "strings"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func TestYq(t *testing.T) {
11 | raw := `
12 | apiVersion: networking.k8s.io/v1
13 | kind: Ingress
14 | metadata:
15 | name: auth-check-cookies
16 | namespace: default
17 | spec:
18 | rules:
19 | - host: "auth-check-cookies"
20 | http:
21 | paths:
22 | - backend:
23 | service:
24 | name: auth-server
25 | port:
26 | number: 80
27 | path: /
28 | pathType: Prefix`
29 | expect := strings.TrimSpace(`
30 | apiVersion: networking.k8s.io/v1
31 | kind: Ingress
32 | metadata:
33 | name: auth-check-cookies
34 | namespace: default
35 | spec:
36 | rules:
37 | - host: "auth-check-cookies"
38 | http:
39 | paths:
40 | - backend:
41 | service:
42 | name: auth-server
43 | port:
44 | number: 80
45 | path: /
46 | pathType: Prefix
47 | ingressClassName: nginx`)
48 | out, err := YqDo(raw, `yq ".spec.ingressClassName=\"nginx\""`)
49 | t.Logf("%v | %v", out, err)
50 | assert.NoError(t, err)
51 | _ = expect
52 | _ = out
53 | assert.Equal(t, expect, out)
54 | }
55 |
--------------------------------------------------------------------------------
/utils/types.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | func SliceToPointerSlice[T any](slice []T) []*T {
4 | pointerSlice := make([]*T, len(slice))
5 | for i, v := range slice {
6 | x := v
7 | pointerSlice[i] = &x
8 | }
9 | return pointerSlice
10 | }
11 |
--------------------------------------------------------------------------------
/utils/wait_test.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "context"
5 | "testing"
6 | "time"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestUtilWithContextAndTimeout(t *testing.T) {
12 | t.Skip("unstable... skip")
13 | // it should run f each period
14 | {
15 | msgChan := make(chan string, 100)
16 | ctx, cancel := context.WithCancel(context.Background())
17 | go func() {
18 | time.Sleep(120 * time.Millisecond)
19 | cancel()
20 | t.Logf("ctx is done")
21 | }()
22 | isTimeout := UtilWithContextAndTimeout(ctx, func() {
23 | msgChan <- "msg"
24 | }, 10*time.Millisecond, 20*time.Millisecond)
25 | close(msgChan)
26 | count := 0
27 | for msg := range msgChan {
28 | _ = msg
29 | count++
30 | }
31 | t.Logf("count is %v\n", count)
32 | assert.Equal(t, isTimeout, false)
33 | }
34 | // it should return with true , if f reach timeout
35 | {
36 | msgChan := make(chan string)
37 | isTimeout := UtilWithContextAndTimeout(context.Background(), func() {
38 | time.Sleep(100 * time.Second)
39 | msgChan <- "should never send"
40 | }, 10*time.Millisecond, 20*time.Millisecond)
41 | assert.Equal(t, isTimeout, true)
42 | select {
43 | case <-msgChan:
44 | assert.Fail(t, "should never receive msg")
45 | default:
46 | assert.True(t, true, "no msg from chan")
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------