├── .circleci └── config.yml ├── .codecov.yml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── golang-ci-lint.yml ├── .gitignore ├── .golangci.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DESIGN.md ├── LICENSE ├── Makefile ├── README.md ├── admiral ├── apis │ └── v1 │ │ └── types.go ├── cmd │ └── admiral │ │ ├── cmd │ │ └── root.go │ │ └── main.go ├── crd │ ├── clientconnectionconfig.yaml │ ├── dependency.yaml │ ├── dependencyproxies.yaml │ ├── globalTraffic.yaml │ ├── outlierdetection.yaml │ ├── routingPolicy.yaml │ └── trafficconfig.yaml ├── docker │ └── Dockerfile.admiral └── pkg │ ├── apis │ └── admiral │ │ ├── filters │ │ └── filters.go │ │ ├── model │ │ ├── clientconnectionconfig.pb.go │ │ ├── clientconnectionconfig.proto │ │ ├── dependency.pb.go │ │ ├── dependency.proto │ │ ├── doc.go │ │ ├── globalrouting.pb.go │ │ ├── globalrouting.proto │ │ ├── outlierdetection.pb.go │ │ ├── outlierdetection.proto │ │ ├── register.go │ │ ├── routingpolicy.pb.go │ │ ├── routingpolicy.proto │ │ └── zz_generated.deepcopy.go │ │ ├── resources.go │ │ ├── routes │ │ ├── handler_test.go │ │ ├── handlers.go │ │ └── routes.go │ │ ├── server │ │ └── server.go │ │ └── v1alpha1 │ │ ├── doc.go │ │ ├── register.go │ │ ├── type.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 │ │ │ └── admiral │ │ │ ├── model │ │ │ ├── admiral_client.go │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ │ ├── doc.go │ │ │ │ └── fake_admiral_client.go │ │ │ └── generated_expansion.go │ │ │ └── v1alpha1 │ │ │ ├── admiral_client.go │ │ │ ├── clientconnectionconfig.go │ │ │ ├── dependency.go │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── fake_admiral_client.go │ │ │ ├── fake_clientconnectionconfig.go │ │ │ ├── fake_dependency.go │ │ │ ├── fake_globaltrafficpolicy.go │ │ │ ├── fake_outlierdetection.go │ │ │ ├── fake_routingpolicy.go │ │ │ └── fake_trafficconfig.go │ │ │ ├── generated_expansion.go │ │ │ ├── globaltrafficpolicy.go │ │ │ ├── outlierdetection.go │ │ │ ├── routingpolicy.go │ │ │ └── trafficconfig.go │ ├── informers │ │ └── externalversions │ │ │ ├── admiral │ │ │ ├── interface.go │ │ │ └── v1alpha1 │ │ │ │ ├── clientconnectionconfig.go │ │ │ │ ├── dependency.go │ │ │ │ ├── globaltrafficpolicy.go │ │ │ │ ├── interface.go │ │ │ │ ├── outlierdetection.go │ │ │ │ ├── routingpolicy.go │ │ │ │ └── trafficconfig.go │ │ │ ├── factory.go │ │ │ ├── generic.go │ │ │ └── internalinterfaces │ │ │ └── factory_interfaces.go │ ├── listers │ │ └── admiral │ │ │ └── v1alpha1 │ │ │ ├── clientconnectionconfig.go │ │ │ ├── dependency.go │ │ │ ├── expansion_generated.go │ │ │ ├── globaltrafficpolicy.go │ │ │ ├── outlierdetection.go │ │ │ ├── routingpolicy.go │ │ │ └── trafficconfig.go │ └── loader │ │ ├── client_loader.go │ │ ├── fake_loader.go │ │ └── kube_loader.go │ ├── clusters │ ├── admiralDatabaseClient.go │ ├── admiralDatabaseClient_test.go │ ├── admiralIgnoreIdentityStateChecker.go │ ├── admiralIgnoreIdentityStateChecker_test.go │ ├── admiralReadWriteLeaseStateChecker.go │ ├── admiralReadWriteLeaseStateChecker_test.go │ ├── admiralStateChecker.go │ ├── clientconnectionconfig_handler.go │ ├── clientconnectionconfig_handler_test.go │ ├── clientdiscovery_handler.go │ ├── clientdiscovery_handler_test.go │ ├── clusters.go │ ├── configwriter.go │ ├── configwriter_test.go │ ├── dependency_handler.go │ ├── dependency_handler_test.go │ ├── deployment_handler.go │ ├── deployment_handler_test.go │ ├── destinationrule_handler.go │ ├── destinationrule_handler_test.go │ ├── dynamoDB.go │ ├── dynamoDB_test.go │ ├── envoyfilter.go │ ├── envoyfilter_test.go │ ├── globaltraffic_handler.go │ ├── globaltraffic_handler_test.go │ ├── handler.go │ ├── handler_test.go │ ├── metrics.go │ ├── mocks_test.go │ ├── outlierdetection_handler.go │ ├── outlierdetection_handler_test.go │ ├── registry.go │ ├── registry_test.go │ ├── rollout_handler.go │ ├── rollout_handler_test.go │ ├── routingpolicy_handler.go │ ├── routingpolicy_handler_test.go │ ├── serviceEntrySuspender.go │ ├── serviceEntrySuspender_test.go │ ├── service_handler.go │ ├── service_handler_test.go │ ├── serviceentry.go │ ├── serviceentry_handler.go │ ├── serviceentry_handler_test.go │ ├── serviceentry_od_test.go │ ├── serviceentry_test.go │ ├── shard_handler.go │ ├── shard_handler_test.go │ ├── sidecar_handler.go │ ├── sidecar_handler_test.go │ ├── testdata │ │ ├── admiralDatabaseClientConfig_invalid.yaml │ │ ├── admiralDatabaseClientConfig_is_valid.yaml │ │ ├── admiralIgnoreIdentityStateChecker_admiralConfig_is_nil.yaml │ │ ├── admiralIgnoreIdentityStateChecker_admiralConfig_is_valid.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList.StateCheckPeriod_is_0.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.ClusterEnvironment_is_empty.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.Region_is_empty.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.Role_is_empty.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.TableName_is_empty.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB_is_empty.yaml │ │ ├── admiralIgnoreIdentityStateChecker_ignoreIdentityList_is_empty.yaml │ │ ├── expectedIdentityIdentityConfiguration.json │ │ ├── fake.config │ │ ├── fake_2.config │ │ ├── identityIdentityConfiguration.json │ │ ├── ppdmeshtestblackholeIdentityConfiguration.json │ │ ├── ppdmeshtestinboundsIdentityConfiguration.json │ │ └── sampleIdentityConfiguration.json │ ├── trafficconfig_handler.go │ ├── trafficconfig_handler_test.go │ ├── types.go │ ├── types_test.go │ ├── util.go │ ├── util_test.go │ ├── virtualservice_handler.go │ ├── virtualservice_handler_test.go │ ├── virtualservice_routing.go │ └── virtualservice_routing_test.go │ ├── controller │ ├── admiral │ │ ├── clientconnectionconfigcontroller.go │ │ ├── clientconnectionconfigcontroller_test.go │ │ ├── configmap.go │ │ ├── configmap_test.go │ │ ├── controller.go │ │ ├── controller_test.go │ │ ├── delegator_mock_test.go │ │ ├── dependency.go │ │ ├── dependency_test.go │ │ ├── deployment.go │ │ ├── deployment_test.go │ │ ├── globaltraffic.go │ │ ├── globaltraffic_test.go │ │ ├── job.go │ │ ├── job_test.go │ │ ├── monovertex.go │ │ ├── monovertex_test.go │ │ ├── node.go │ │ ├── node_test.go │ │ ├── outlierdetection.go │ │ ├── outlierdetection_test.go │ │ ├── rollouts.go │ │ ├── rollouts_test.go │ │ ├── routingpolicy.go │ │ ├── routingpolicy_test.go │ │ ├── service.go │ │ ├── service_test.go │ │ ├── shard.go │ │ ├── shard_test.go │ │ ├── trafficconfig.go │ │ ├── util_test.go │ │ ├── vertex.go │ │ └── vertex_test.go │ ├── common │ │ ├── cache.go │ │ ├── common.go │ │ ├── common_test.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── metrics.go │ │ ├── metrics_test.go │ │ ├── rolloutcommon.go │ │ ├── rolloutcommon_test.go │ │ ├── types.go │ │ └── types_test.go │ ├── istio │ │ ├── destinationrule.go │ │ ├── destinationrule_test.go │ │ ├── serviceentry.go │ │ ├── serviceentry_test.go │ │ ├── sidecar.go │ │ ├── sidecar_test.go │ │ ├── virtualservice.go │ │ └── virtualservice_test.go │ ├── secret │ │ ├── resolver │ │ │ ├── defaultresolver.go │ │ │ ├── defaultresolver_test.go │ │ │ └── resolver.go │ │ ├── secretcontroller.go │ │ └── secretcontroller_test.go │ └── util │ │ ├── migration.go │ │ ├── migration_test.go │ │ ├── util.go │ │ └── util_test.go │ ├── core │ └── vsrouting │ │ ├── routedestination.go │ │ └── routedestination_test.go │ ├── mocks │ └── ConfigWriter.go │ ├── monitoring │ ├── metrics.go │ └── monitoring.go │ ├── registry │ ├── config.go │ ├── registry.go │ ├── registry_test.go │ ├── testdata │ │ ├── record1IdentityConfiguration.json │ │ ├── record2IdentityConfiguration.json │ │ └── sampleIdentityConfiguration.json │ └── testutils.go │ ├── test │ ├── mock.go │ ├── resources │ │ └── admins@fake-cluster.k8s.local │ └── types.go │ ├── types │ └── types.go │ └── util │ ├── baseClient.go │ ├── baseClient_test.go │ ├── constants.go │ ├── util.go │ ├── util_test.go │ └── variables.go ├── docs ├── API_Orchestration_using_Istio_and_Admiral.md ├── Admiral-DynamoDB-view.png ├── Admiral-dynamoDB-DR.png ├── Admiral-health-check.png ├── Admiral-state-changes.png ├── Admiral_Diagram.png ├── Architecture.md ├── Compatibility.md ├── DisasterRecovery.md ├── DynamoDBBasedDR.md ├── Examples.md ├── Index.md ├── Processes.md ├── Release-steps.md ├── ReleaseNotes.md ├── _config.yml └── diagrams │ ├── admiral.svg │ ├── api-orchestration_deployment-flow.png │ └── api-orchestration_using_istio_and_admiral.png ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt ├── update-codegen.sh ├── update-k8s.sh └── verify-codegen.sh ├── install ├── admiral │ ├── base │ │ ├── crds.yaml │ │ ├── deployments.yaml │ │ ├── kustomization.yaml │ │ ├── role_bindings.yaml │ │ ├── roles.yaml │ │ ├── service_accounts.yaml │ │ └── services.yaml │ └── overlays │ │ └── demosinglecluster │ │ ├── envconfig_values.yaml │ │ ├── kustomization.yaml │ │ └── ns.yaml ├── admiralremote │ └── base │ │ ├── crds.yaml │ │ ├── kustomization.yaml │ │ └── remote.yaml ├── prometheus │ └── prometheus.yaml ├── sample │ ├── base │ │ ├── greeting.yaml │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── webapp.yaml │ ├── depProxyExample.yaml │ ├── greeting_preview.yaml │ ├── greetings-ccc.yaml │ ├── grpc-client.yaml │ ├── gtp-priority.yaml │ ├── gtp.yaml │ ├── gtp_failover.yaml │ ├── gtp_topology.yaml │ ├── od.yaml │ ├── overlays │ │ ├── deployment │ │ │ ├── greeting.yaml │ │ │ └── kustomization.yaml │ │ ├── grpc │ │ │ ├── grpc-server.yaml │ │ │ └── kustomization.yaml │ │ ├── job │ │ │ ├── job.yaml │ │ │ ├── kustomization.yaml │ │ │ └── webapp.yaml │ │ ├── numaflow │ │ │ ├── kustomization.yaml │ │ │ ├── monovertex.yaml │ │ │ └── webapp.yaml │ │ ├── remote │ │ │ ├── greeting-deployment.yaml │ │ │ ├── greeting.yaml │ │ │ └── kustomization.yaml │ │ ├── rollout-bluegreen │ │ │ ├── greeting.yaml │ │ │ └── kustomization.yaml │ │ └── rollout-canary │ │ │ ├── greeting.yaml │ │ │ └── kustomization.yaml │ ├── proxy.yaml │ ├── rp.yaml │ ├── sample_dep.yaml │ └── trafficconfig.yaml └── scripts │ ├── cleanup.sh │ ├── cluster-secret.sh │ ├── dev_setup.sh │ ├── install_admiral.sh │ ├── install_numaflow.sh │ ├── install_prometheus.sh │ ├── install_rollouts.sh │ └── install_sample_services.sh ├── logo ├── admiral_logo_final-01.jpg ├── admiral_logo_final-01.svg ├── admiral_logo_final-02.jpg ├── admiral_logo_final.ai ├── admiral_logo_final.svg ├── img │ ├── admiral_logo_final_admiral_on_dark.jpg │ ├── admiral_logo_final_admiral_on_dark_text.jpg │ ├── admiral_logo_final_admiral_on_white.jpg │ └── admiral_logo_final_admiral_on_white_text.jpg ├── png │ ├── admiral_logo_final-darkbackground_text.png │ ├── admiral_logo_final-whitebg_no_text.png │ ├── admiral_logo_final_admiral_on_dark.png │ └── admiral_logo_final_admiral_on_white_text.png └── svg │ ├── admiral_logo_final-darkbackground_text.svg │ ├── admiral_logo_final-whitebg_no_text.svg │ ├── admiral_logo_final_admiral_on_dark.svg │ └── admiral_logo_final_admiral_on_white_text.svg └── tests ├── README.md ├── cleanup.sh ├── client_discovery_test.sh ├── create_cluster.sh ├── install_istio.sh ├── master_run.sh ├── run.sh ├── test1.sh ├── test2.sh ├── test3.sh ├── test4.sh ├── test5.sh └── test6.sh /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 60..100 3 | round: down 4 | precision: 2 5 | 6 | ignore: 7 | - admiral/pkg/client/**/* -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | @aattuluri 2 | @nirvanagit 3 | @shriramsharma 4 | @kpharasi 5 | @vinay-g 6 | @vrushalijoshi 7 | @virajrk 8 | @rtay1188 9 | @Punakshi 10 | @psikka1 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Steps To Reproduce** 14 | 15 | **Expected behavior** 16 | A clear and concise description of what you expected to happen. 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Checklist 2 | 🚨 Please review this repository's [contribution guidelines](./CONTRIBUTING.md). 3 | 4 | - [ ] I've read and agree to the project's contribution guidelines. 5 | - [ ] I'm requesting to **pull a topic/feature/bugfix branch**. 6 | - [ ] I checked that my code additions will pass code linting checks and unit tests. 7 | - [ ] I updated unit and integration tests (if applicable). 8 | - [ ] I'm ready to notify the team of this contribution. 9 | 10 | ### Description 11 | What does this change do and why? 12 | 13 | [Link to related ISSUE] 14 | 15 | Thank you! -------------------------------------------------------------------------------- /.github/workflows/golang-ci-lint.yml: -------------------------------------------------------------------------------- 1 | #name: golangci-lint 2 | #on: 3 | # push: 4 | # tags: 5 | # - v* 6 | # branches: 7 | # - master 8 | # - main 9 | # pull_request: 10 | #jobs: 11 | # golangci: 12 | # name: lint 13 | # runs-on: ubuntu-latest 14 | # steps: 15 | # - uses: actions/checkout@v2 16 | # - uses: actions/setup-go@v3 17 | # with: 18 | # go-version: '1.22.2' 19 | # - name: golangci-lint 20 | # uses: golangci/golangci-lint-action@v2 21 | # with: 22 | # # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. 23 | # version: v1.58.1 24 | # skip-go-installation: true 25 | # 26 | # # Optional: working directory, useful for monorepos 27 | # # working-directory: somedir 28 | # 29 | # # Optional: golangci-lint command line arguments. 30 | # args: >- 31 | # --skip-dirs=admiral/pkg/client/clientset/versioned 32 | # --tests=false 33 | # --timeout=5m 34 | # 35 | # # Optional: show only new issues if it's a pull request. The default value is `false`. 36 | # # only-new-issues: true 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .idea/vcs.xml 3 | 4 | out/* 5 | out.yaml 6 | c.out.tmp 7 | *.tar.gz 8 | *.out 9 | *.prof 10 | istio-* 11 | .DS_Store 12 | cobertura-coverage.xml 13 | .vscode 14 | 15 | .qodo 16 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | #name: golangci-lint 2 | #on: 3 | # push: 4 | # tags: 5 | # - v* 6 | # branches: 7 | # - master 8 | # - main 9 | # pull_request: 10 | #jobs: 11 | # golangci: 12 | # name: lint 13 | # runs-on: ubuntu-latest 14 | # steps: 15 | # - uses: actions/checkout@v2 16 | # - uses: actions/setup-go@v3 17 | # with: 18 | # go-version: '1.22.3' 19 | # - name: golangci-lint 20 | # uses: golangci/golangci-lint-action@v2 21 | # with: 22 | # # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. 23 | # version: v1.58.1 24 | # skip-go-installation: true 25 | # 26 | # # Optional: working directory, useful for monorepos 27 | # # working-directory: somedir 28 | # 29 | # # Optional: golangci-lint command line arguments. 30 | # args: >- 31 | # --skip-dirs=admiral/pkg/client/clientset/versioned 32 | # --tests=false 33 | # --timeout=5m || true 34 | # 35 | # # Optional: show only new issues if it's a pull request. The default value is `false`. 36 | # # only-new-issues: true -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at Anil_Attuluri@intuit.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /DESIGN.md: -------------------------------------------------------------------------------- 1 | # Admiral 2 | -------------------------------------------------------------------------------- /admiral/apis/v1/types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | const ( 4 | Admiral = "Admiral" 5 | ) 6 | 7 | type AdmiralConfig struct { 8 | IdpsConfig IdpsConfig `yaml:"idps,omitempty"` 9 | IgnoreIdentityList IgnoreIdentityList `yaml:"ignoreIdentityList,omitempty"` 10 | WorkloadDatabase DynamoDB `yaml:"workloadDynamoDB,omitempty"` 11 | DynamicConfigDatabase DynamoDB `yaml:"dynamicConfigDynamoDB,omitempty"` 12 | } 13 | 14 | type IgnoreIdentityList struct { 15 | StateCheckerPeriodInSeconds int `yaml:"stateCheckerPeriodInSeconds,omitempty"` 16 | DynamoDB DynamoDB `yaml:"dynamoDB,omitempty"` 17 | } 18 | 19 | type DynamoDB struct { 20 | TableName string `yaml:"tableName,omitempty"` 21 | Region string `yaml:"region,omitempty"` 22 | Role string `yaml:"role,omitempty"` 23 | ClusterEnvironment string `yaml:"clusterEnvironment,omitempty"` 24 | } 25 | 26 | type IdpsConfig struct { 27 | ApiKeyId string `yaml:"api-key-id,omitempty"` 28 | ApiSecretKey string `yaml:"api-secret-key,omitempty"` 29 | ApiEndPoint string `yaml:"api-endpoint,omitempty"` 30 | MgmtSecretKey string `yaml:"mgmt-api-secret-key,omitempty"` 31 | MgmtEndpoint string `yaml:"mgmt-endpoint,omitempty"` 32 | MgmtTempCredExpiry int32 `yaml:"mgmt-temp-cred-expiry,omitempty"` 33 | PolicyId string `yaml:"policy-id,omitempty"` 34 | ExpiryRequest int32 `yaml:"temporary-credentials-expiry-requested-mins,omitempty"` 35 | KubeConfigSecretFolder string `yaml:"kubeconfig-secret-folder,omitempty"` 36 | } 37 | -------------------------------------------------------------------------------- /admiral/cmd/admiral/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/istio-ecosystem/admiral/admiral/cmd/admiral/cmd" 7 | ) 8 | 9 | func main() { 10 | rootCmd := cmd.GetRootCmd(os.Args[1:]) 11 | 12 | if err := rootCmd.Execute(); err != nil { 13 | os.Exit(-1) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /admiral/crd/dependency.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: dependencies.admiral.io 5 | spec: 6 | group: admiral.io 7 | names: 8 | kind: Dependency 9 | plural: dependencies 10 | scope: Namespaced 11 | versions: 12 | - name: v1alpha1 13 | schema: 14 | openAPIV3Schema: 15 | description: generic cdr object to wrap the dependency api 16 | properties: 17 | apiVersion: 18 | description: 'APIVersion defines the versioned schema of this representation 19 | of an object. Servers should convert recognized schemas to the latest 20 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 21 | type: string 22 | kind: 23 | description: 'Kind is a string value representing the REST resource this 24 | object represents. Servers may infer this from the endpoint the client 25 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 26 | type: string 27 | metadata: 28 | type: object 29 | spec: 30 | properties: 31 | destinations: 32 | description: 'REQUIRED: A list of workloads that source workload depends 33 | on.' 34 | items: 35 | type: string 36 | type: array 37 | identityLabel: 38 | description: 'REQUIRED: the label on the workload for selecting source 39 | and destination' 40 | type: string 41 | source: 42 | description: 'REQUIRED: identifier for the source workload' 43 | type: string 44 | type: object 45 | required: 46 | - metadata 47 | - spec 48 | type: object 49 | served: true 50 | storage: true -------------------------------------------------------------------------------- /admiral/crd/outlierdetection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: outlierdetections.admiral.io 5 | spec: 6 | group: admiral.io 7 | names: 8 | kind: OutlierDetection 9 | listKind: OutlierDetectionList 10 | plural: outlierdetections 11 | singular: outlierdetection 12 | shortNames: 13 | - od 14 | - ods 15 | scope: Namespaced 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: generic cdr object to wrap the OutlierDetection api 21 | properties: 22 | apiVersion: 23 | description: 'APIVersion defines the versioned schema of this representation 24 | of an object. Servers should convert recognized schemas to the latest 25 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 26 | type: string 27 | kind: 28 | description: 'Kind is a string value representing the REST resource this 29 | object represents. Servers may infer this from the endpoint the client 30 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 31 | type: string 32 | metadata: 33 | type: object 34 | spec: 35 | properties: 36 | outlier_config: 37 | description: 'REQUIRED: base outlier configuration.' 38 | properties: 39 | base_ejection_time: 40 | description: 'REQUIRED: Minimum duration of time in seconds, the 41 | endpoint will be ejected' 42 | format: int64 43 | type: integer 44 | consecutive_gateway_errors: 45 | description: 'REQUIRED: No. of consecutive failures in specified 46 | interval after which the endpoint will be ejected' 47 | format: int32 48 | type: integer 49 | interval: 50 | description: 'REQUIRED: Time interval between ejection sweep analysis' 51 | format: int64 52 | type: integer 53 | type: object 54 | selector: 55 | additionalProperties: 56 | type: string 57 | description: 'REQUIRED: One or more labels that indicate a specific 58 | set of pods/VMs on which this outlier configuration should be applied. 59 | The scope of label search is restricted to namespace mark for mesh 60 | enablement this will scan all cluster and namespace' 61 | type: object 62 | type: object 63 | status: 64 | properties: 65 | clustersSynced: 66 | format: int32 67 | type: integer 68 | state: 69 | type: string 70 | required: 71 | - clustersSynced 72 | - state 73 | type: object 74 | required: 75 | - metadata 76 | - spec 77 | type: object 78 | served: true 79 | storage: true -------------------------------------------------------------------------------- /admiral/crd/routingPolicy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: routingpolicies.admiral.io 5 | spec: 6 | group: admiral.io 7 | version: v1alpha1 8 | names: 9 | kind: RoutingPolicy 10 | plural: routingpolicies 11 | shortNames: 12 | - rp 13 | - rps 14 | scope: Namespaced -------------------------------------------------------------------------------- /admiral/docker/Dockerfile.admiral: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | 3 | RUN set -ex; \ 4 | apt-get update; \ 5 | apt-get install -qy --no-install-recommends curl; \ 6 | rm -rf /var/lib/apt/lists/* 7 | 8 | COPY ./out/admiral /usr/local/admiral 9 | 10 | RUN chmod +x /usr/local/admiral 11 | 12 | ENTRYPOINT ["/usr/local/admiral"] 13 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/filters/filters.go: -------------------------------------------------------------------------------- 1 | package filters 2 | 3 | import ( 4 | "io/ioutil" 5 | "log" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | /* 11 | * func for the "middleware" or filters for example Access logging or processing Authn/z 12 | */ 13 | 14 | func Logger(inner http.Handler, name string) http.Handler { 15 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 16 | start := time.Now() 17 | 18 | inner.ServeHTTP(w, r) 19 | body, _ := ioutil.ReadAll(r.Body) 20 | 21 | log.Printf( 22 | "Access Logger %s\t%s\t%s\t%s\t%s", 23 | r.Method, 24 | r.RequestURI, 25 | name, 26 | time.Since(start), 27 | string(body), 28 | ) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/clientconnectionconfig.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package admiral.global.v1alpha; 4 | 5 | option go_package = "model"; 6 | 7 | message ClientConnectionConfig { 8 | 9 | ConnectionPool connectionPool = 1; 10 | 11 | Tunnel tunnel = 2; 12 | } 13 | 14 | message ConnectionPool { 15 | 16 | message TcpKeepalive { 17 | 18 | uint32 probes = 1; 19 | 20 | string time = 2; 21 | 22 | string interval = 3; 23 | 24 | } 25 | 26 | message TCP { 27 | 28 | // Maximum number of HTTP1 /TCP connections to a destination host. 29 | int32 maxConnections = 1; 30 | 31 | string connectTimeout = 2; 32 | 33 | TcpKeepalive tcpKeepalive = 3; 34 | 35 | // The maximum duration of a connection 36 | string maxConnectionDuration = 4; 37 | } 38 | 39 | // HTTP connection pool settings 40 | message HTTP { 41 | 42 | // Maximum number of pending HTTP requests to a destination. 43 | int32 http1MaxPendingRequests = 1; 44 | 45 | // Maximum number of requests to a backend 46 | int32 http2MaxRequests = 2; 47 | 48 | // Maximum number of requests per connection to a backend. 49 | int32 maxRequestsPerConnection = 3; 50 | 51 | int32 maxRetries = 4; 52 | 53 | string idleTimeout = 5; 54 | 55 | enum H2UpgradePolicy { 56 | DEFAULT = 0; 57 | DO_NOT_UPGRADE = 1; 58 | UPGRADE = 2; 59 | }; 60 | H2UpgradePolicy h2UpgradePolicy = 6; 61 | 62 | bool useClientProtocol = 7; 63 | }; 64 | 65 | 66 | TCP tcp = 1; 67 | 68 | HTTP http = 2; 69 | 70 | } 71 | 72 | message Tunnel { 73 | string protocol = 1; 74 | 75 | string targetHost = 2; 76 | 77 | uint32 targetPort = 3; 78 | } -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/dependency.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package admiral.global.v1alpha; 4 | 5 | option go_package = "model"; 6 | 7 | // ``` 8 | // apiVersion: admiral.io/v1alpha1 9 | // kind: Dependency 10 | // metadata: 11 | // name: my-dependency 12 | // spec: 13 | // identityLabel: identity 14 | // source: source-identity-1 15 | // destinations: 16 | // - dest-identity-1 17 | // - dest-identity-2 18 | // - dest-identity-3 19 | // - dest-identity-4 20 | // - dest-identity-5 21 | // 22 | // ``` 23 | 24 | message Dependency { 25 | 26 | // REQUIRED: identifier for the source workload 27 | string source = 1; 28 | 29 | // REQUIRED: the label on the workload for selecting source and destination 30 | string identityLabel = 2; 31 | 32 | // REQUIRED: A list of workloads that source workload depends on. 33 | repeated string destinations = 3; 34 | } -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/doc.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | //go:generate protoc -I . dependency.proto --go_out=plugins=grpc:. 4 | //go:generate protoc -I . globalrouting.proto --go_out=plugins=grpc:. 5 | //go:generate protoc -I . routingpolicy.proto --go_out=plugins=grpc:. 6 | //go:generate protoc -I . dependencyproxy.proto --go_out=plugins=grpc:. 7 | //go:generate protoc -I . outlierdetection.proto --go_out=plugins=grpc:. 8 | //go:generate protoc -I . clientconnectionconfig.proto --go_out=plugins=grpc:. 9 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 10 | // +k8s:deepcopy-gen=package,register 11 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/globalrouting.proto: -------------------------------------------------------------------------------- 1 | 2 | 3 | syntax = "proto3"; 4 | 5 | package admiral.global.v1alpha; 6 | 7 | option go_package = "model"; 8 | 9 | 10 | // ``` 11 | // apiVersion: admiral.io/v1alpha1 12 | // kind: GlobalTrafficPolicy 13 | // metadata: 14 | // name: my-routing 15 | // spec: 16 | // selector: 17 | // identity: my-identity 18 | // env: prd 19 | // policy: 20 | // - dnsPrefix: prd.accounts.global 21 | // lbType: topology 22 | // - dnsPrefix: prd.accounts-us-west2 23 | // lbType: failover 24 | // target: 25 | // - region: us-west2 26 | // weight: 90 27 | // - region: us-east2 28 | // weight: 10 29 | // - dnsPrefix: prd.accounts-us-east2 30 | // lbType: failover 31 | // target: 32 | // - region: us-west2 33 | // weight: 10 34 | // - region: us-east2 35 | // weight: 90 36 | // outlier_detection: 37 | // base_ejection_time: 180 38 | // consecutive_gateway_errors: 100 39 | // interval: 60 40 | // 41 | // ``` 42 | 43 | message GlobalTrafficPolicy { 44 | // REQUIRED: A list host name . 45 | repeated TrafficPolicy policy = 1; 46 | 47 | // REQUIRED: One or more labels that indicate a specific set of pods/VMs 48 | // on which this global routing policy should be applied. The scope of 49 | // label search is restricted to namespace mark for mesh enablement 50 | // this will scan all cluster and namespace 51 | map selector = 2; 52 | } 53 | 54 | // TrafficPolicy describes routing for a hostname. 55 | message TrafficPolicy { 56 | 57 | // REQUIRED: dns that can be used by client. This name will have the 58 | // traffic type applied to it 59 | string dns = 1 [deprecated=true]; 60 | 61 | // REQUIRED: type of global load distrubtion 62 | LbType lbType = 2; 63 | 64 | 65 | enum LbType { 66 | 67 | //Traffic with be routed to local locality first 68 | //if there are no health instances in the local locality traffic will be routed to 69 | //remote locality 70 | TOPOLOGY = 0; 71 | 72 | FAILOVER = 1; 73 | } 74 | 75 | //weigth of primary and secondary must each 100 76 | repeated TrafficGroup target = 3; 77 | 78 | //REQUIRED: dnsPrefix that will be prefixed for the service names being generated with this traffic policy 79 | //Ex: dnsPrefix = west => generated service name = west.stage.servicename.global 80 | string dnsPrefix = 4; 81 | 82 | message OutlierDetection { 83 | //REQUIRED: Minimum duration of time in seconds, the endpoint will be ejected 84 | int64 base_ejection_time = 1; 85 | //REQUIRED: No. of consecutive failures in specified interval after which the endpoint will be ejected 86 | uint32 consecutive_gateway_errors = 2; 87 | //REQUIRED: Time interval between ejection sweep analysis 88 | int64 interval = 3; 89 | } 90 | 91 | //OPTIONAL: to configure the outlierDetection in DestinationRule 92 | OutlierDetection outlier_detection = 5; 93 | } 94 | 95 | message TrafficGroup { 96 | 97 | //region for the traffic 98 | string region = 1; 99 | //weight for traffic this region should get. 100 | int32 weight = 2; 101 | 102 | } -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/outlierdetection.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package admiral.global.v1alpha; 4 | 5 | option go_package = "model"; 6 | 7 | // ``` 8 | // apiVersion: admiral.io/v1alpha1 9 | // kind: OutlierDetection 10 | // metadata: 11 | // name: my-outlier-configuration 12 | // spec: 13 | // selector: 14 | // identity: my-identity 15 | // env: prd 16 | // outlier_config: 17 | // base_ejection_time: 180 18 | // consecutive_gateway_errors: 100 19 | // interval: 60 20 | // ``` 21 | 22 | message OutlierDetection { 23 | // REQUIRED: base outlier configuration. 24 | OutlierConfig outlier_config = 1; 25 | 26 | // REQUIRED: One or more labels that indicate a specific set of pods/VMs 27 | // on which this outlier configuration should be applied. The scope of 28 | // label search is restricted to namespace mark for mesh enablement 29 | // this will scan all cluster and namespace 30 | map selector = 2; 31 | } 32 | 33 | // OutlierConfig describes routing for a endpoint. 34 | message OutlierConfig { 35 | 36 | //REQUIRED: Minimum duration of time in seconds, the endpoint will be ejected 37 | int64 base_ejection_time = 1; 38 | 39 | //REQUIRED: No. of consecutive failures in specified interval after which the endpoint will be ejected 40 | uint32 consecutive_gateway_errors = 2; 41 | 42 | //REQUIRED: Time interval between ejection sweep analysis 43 | int64 interval = 3; 44 | } -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/register.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral" 5 | "k8s.io/apimachinery/pkg/runtime" 6 | "k8s.io/apimachinery/pkg/runtime/schema" 7 | 8 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | // GroupVersion is the identifier for the API which includes 12 | // the name of the group and the version of the API 13 | var SchemeGroupVersion = schema.GroupVersion{ 14 | Group: admiral.GroupName, 15 | Version: "v1alpha1", 16 | } 17 | 18 | // create a SchemeBuilder which uses functions to add types to 19 | // the scheme 20 | var ( 21 | SchemeBuilder runtime.SchemeBuilder 22 | localSchemeBuilder = &SchemeBuilder 23 | AddToScheme = localSchemeBuilder.AddToScheme 24 | ) 25 | 26 | func Resource(resource string) schema.GroupResource { 27 | return SchemeGroupVersion.WithResource(resource).GroupResource() 28 | } 29 | 30 | func init() { 31 | // We only register manually written functions here. The registration of the 32 | // generated functions takes place in the generated files. The separation 33 | // makes the code compile even when the generated files are missing. 34 | localSchemeBuilder.Register(addKnownTypes) 35 | } 36 | 37 | // addKnownTypes adds our types to the API scheme by registering 38 | // MyResource and MyResourceList 39 | func addKnownTypes(scheme *runtime.Scheme) error { 40 | //scheme.AddUnversionedTypes( 41 | // SchemeGroupVersion, 42 | // &Dependency{}, 43 | // &DependencyList{}, 44 | // &GlobalTrafficPolicy{}, 45 | // &GlobalTrafficPolicyList{}, 46 | //) 47 | 48 | scheme.AddKnownTypes( 49 | SchemeGroupVersion, 50 | ) 51 | 52 | // register the type in the scheme 53 | meta_v1.AddToGroupVersion(scheme, SchemeGroupVersion) 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/model/routingpolicy.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package admiral.global.v1alpha; 4 | 5 | option go_package = "model"; 6 | 7 | //``` 8 | // apiVersion: admiral.io/v1alpha1 9 | // kind: RoutingPolicy 10 | // metadata: 11 | // name: greeting-routing-policy 12 | // annotations: 13 | // admiral.io/env: stage 14 | // labels: 15 | // identity: greeting 16 | // spec: 17 | // plugin: greeting 18 | // hosts: 19 | // - qal.greeting.mesh 20 | // config: 21 | // cachePrefix: cache-v1 22 | // cachettlSec: "86400" 23 | // dispatcherUrl: qal.greeting.dispatcher.mesh 24 | // algo: greetingDispatcher 25 | // pathPrefix: "/wpcatalog,/consumercatalog,/v1/company/{id}/auth/hydrate,/consumercatalog" 26 | //``` 27 | 28 | message RoutingPolicy { 29 | string plugin = 1; 30 | repeated string hosts = 2; 31 | map config = 3; 32 | } 33 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/resources.go: -------------------------------------------------------------------------------- 1 | package admiral 2 | 3 | const GroupName = "admiral.io" 4 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/filters" 8 | "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/server" 9 | "github.com/istio-ecosystem/admiral/admiral/pkg/controller/common" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | ) 12 | 13 | var Filter = server.Filters{ 14 | server.Filter{HandlerFunc: filters.Logger}, 15 | } 16 | 17 | func NewAdmiralAPIServer(opts *RouteOpts) server.Routes { 18 | // create the config from the path 19 | config, err := opts.RemoteRegistry.ClientLoader.LoadKubeClientFromPath(opts.KubeconfigPath) 20 | if err != nil || config == nil { 21 | log.Printf("could not retrieve kubeconfig: %v", err) 22 | } 23 | 24 | return server.Routes{ 25 | 26 | server.Route{ 27 | Name: "Success health check", 28 | Method: "GET", 29 | Pattern: "/health/ready", 30 | HandlerFunc: opts.ReturnSuccessGET, 31 | }, 32 | server.Route{ 33 | Name: "Get list of clusters admiral is watching", 34 | Method: "GET", 35 | Pattern: "/clusters", 36 | HandlerFunc: opts.GetClusters, 37 | }, 38 | server.Route{ 39 | Name: "Get list service entries for a given cluster", 40 | Method: "GET", 41 | Pattern: "/cluster/{clustername}/serviceentries", 42 | HandlerFunc: opts.GetServiceEntriesByCluster, 43 | }, 44 | server.Route{ 45 | Name: "Get list service entries for a given identity", 46 | Method: "GET", 47 | Pattern: "/identity/{identity}/serviceentries", 48 | HandlerFunc: opts.GetServiceEntriesByIdentity, 49 | }, 50 | server.Route{ 51 | Name: "Get the GlobalTrafficPolicy based on the env and identity/asset alias", 52 | Method: "GET", 53 | Pattern: "/identity/{identity}/globaltrafficpolicy", 54 | Query: "env", 55 | HandlerFunc: opts.GetGlobalTrafficPolicyByIdentityAndEnv, 56 | }, 57 | } 58 | } 59 | 60 | func NewMetricsServer() server.Routes { 61 | 62 | if common.GetMetricsEnabled() { 63 | return server.Routes{ 64 | server.Route{ 65 | Name: "Get metrics in prometheus format", 66 | Method: "GET", 67 | Pattern: "/metrics", 68 | HandlerFunc: promhttp.Handler().ServeHTTP, 69 | }, 70 | } 71 | } 72 | return server.Routes{ 73 | server.Route{ 74 | Name: "Noop metrics", 75 | Method: "GET", 76 | Pattern: "/metrics", 77 | HandlerFunc: Noop, 78 | }, 79 | } 80 | } 81 | 82 | func Noop(w http.ResponseWriter, r *http.Request) { 83 | w.WriteHeader(http.StatusOK) 84 | } 85 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/gorilla/mux" 11 | "github.com/istio-ecosystem/admiral/admiral/pkg/clusters" 12 | 13 | _ "net/http/pprof" 14 | ) 15 | 16 | type Service struct { 17 | Port int 18 | ctx context.Context 19 | server http.Server 20 | remoteRegistry *clusters.RemoteRegistry 21 | } 22 | 23 | // filter definition as a func 24 | type FilterHandlerFunc func(inner http.Handler, name string) http.Handler 25 | 26 | // structs used to collect routes and filters 27 | type Filter struct { 28 | HandlerFunc FilterHandlerFunc 29 | } 30 | 31 | type Route struct { 32 | Name string 33 | Method string 34 | Pattern string 35 | Query string 36 | HandlerFunc http.HandlerFunc 37 | FilterChain Filters 38 | } 39 | 40 | type Routes []Route 41 | 42 | type Filters []Filter 43 | 44 | func (s *Service) Start(ctx context.Context, port int, routes Routes, filter []Filter, remoteRegistry *clusters.RemoteRegistry) { 45 | 46 | s.ctx = ctx 47 | s.Port = port 48 | s.remoteRegistry = remoteRegistry 49 | 50 | go waitForStop(s) 51 | 52 | router := s.newRouter(routes, filter) 53 | if port == 8080 { 54 | router.PathPrefix("/debug/").Handler(http.DefaultServeMux) 55 | } 56 | 57 | s.server = http.Server{Addr: ":" + strconv.Itoa(port), Handler: router} 58 | 59 | log.Printf("Starting server on port=%d", port) 60 | log.Fatalln(s.server.ListenAndServe()) 61 | 62 | } 63 | 64 | func (s *Service) newRouter(routes Routes, filter []Filter) *mux.Router { 65 | 66 | router := mux.NewRouter().StrictSlash(true) 67 | for _, route := range routes { 68 | 69 | var handler http.Handler 70 | handler = route.HandlerFunc 71 | 72 | for _, filter := range filter { 73 | handler = filter.HandlerFunc(handler, route.Name) 74 | } 75 | 76 | router.Methods(route.Method). 77 | Path(route.Pattern). 78 | Name(route.Name). 79 | Handler(handler) 80 | 81 | if route.Query != "" { 82 | queries := strings.Split(route.Query, ",") 83 | for _, query := range queries { 84 | router.Queries(query, "{query}") 85 | } 86 | } 87 | } 88 | 89 | return router 90 | } 91 | 92 | func waitForStop(s *Service) { 93 | for range s.ctx.Done() { 94 | log.Println("context done stopping server") 95 | err := s.stop() 96 | if err != nil { 97 | log.Println("error stopping server: ", err) 98 | } 99 | } 100 | } 101 | 102 | func (s *Service) stop() error { 103 | return s.server.Close() 104 | } 105 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // +k8s:deepcopy-gen=package 2 | // +groupName=admiral.io 3 | package v1alpha1 4 | -------------------------------------------------------------------------------- /admiral/pkg/apis/admiral/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | package v1alpha1 2 | 3 | import ( 4 | "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral" 5 | 6 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 7 | 8 | "k8s.io/apimachinery/pkg/runtime" 9 | "k8s.io/apimachinery/pkg/runtime/schema" 10 | ) 11 | 12 | // GroupVersion is the identifier for the API which includes 13 | // the name of the group and the version of the API 14 | var SchemeGroupVersion = schema.GroupVersion{ 15 | Group: admiral.GroupName, 16 | Version: "v1alpha1", 17 | } 18 | 19 | // create a SchemeBuilder which uses functions to add types to 20 | // the scheme 21 | var ( 22 | SchemeBuilder runtime.SchemeBuilder 23 | localSchemeBuilder = &SchemeBuilder 24 | AddToScheme = localSchemeBuilder.AddToScheme 25 | ) 26 | 27 | func Resource(resource string) schema.GroupResource { 28 | return SchemeGroupVersion.WithResource(resource).GroupResource() 29 | } 30 | 31 | func init() { 32 | // We only register manually written functions here. The registration of the 33 | // generated functions takes place in the generated files. The separation 34 | // makes the code compile even when the generated files are missing. 35 | localSchemeBuilder.Register(addKnownTypes) 36 | } 37 | 38 | // addKnownTypes adds our types to the API scheme by registering 39 | // MyResource and MyResourceList 40 | func addKnownTypes(scheme *runtime.Scheme) error { 41 | //scheme.AddUnversionedTypes( 42 | // SchemeGroupVersion, 43 | // &Dependency{}, 44 | // &DependencyList{}, 45 | // &GlobalTrafficPolicy{}, 46 | // &GlobalTrafficPolicyList{}, 47 | //) 48 | 49 | scheme.AddKnownTypes( 50 | SchemeGroupVersion, 51 | &ClientConnectionConfig{}, 52 | &ClientConnectionConfigList{}, 53 | &Dependency{}, 54 | &DependencyList{}, 55 | &GlobalTrafficPolicy{}, 56 | &GlobalTrafficPolicyList{}, 57 | &OutlierDetection{}, 58 | &OutlierDetectionList{}, 59 | &RoutingPolicy{}, 60 | &RoutingPolicyList{}, 61 | &TrafficConfig{}, 62 | &TrafficConfigList{}, 63 | ) 64 | 65 | // register the type in the scheme 66 | meta_v1.AddToGroupVersion(scheme, SchemeGroupVersion) 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /admiral/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 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/fake/clientset_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 client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | clientset "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned" 23 | admiralv1alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned/typed/admiral/v1alpha1" 24 | fakeadmiralv1alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned/typed/admiral/v1alpha1/fake" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/apimachinery/pkg/watch" 27 | "k8s.io/client-go/discovery" 28 | fakediscovery "k8s.io/client-go/discovery/fake" 29 | "k8s.io/client-go/testing" 30 | ) 31 | 32 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 33 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 34 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 35 | // for a real clientset and is mostly useful in simple unit tests. 36 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 37 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 38 | for _, obj := range objects { 39 | if err := o.Add(obj); err != nil { 40 | panic(err) 41 | } 42 | } 43 | 44 | cs := &Clientset{tracker: o} 45 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 46 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 47 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 48 | gvr := action.GetResource() 49 | ns := action.GetNamespace() 50 | watch, err := o.Watch(gvr, ns) 51 | if err != nil { 52 | return false, nil, err 53 | } 54 | return true, watch, nil 55 | }) 56 | 57 | return cs 58 | } 59 | 60 | // Clientset implements clientset.Interface. Meant to be embedded into a 61 | // struct to get a default implementation. This makes faking out just the method 62 | // you want to test easier. 63 | type Clientset struct { 64 | testing.Fake 65 | discovery *fakediscovery.FakeDiscovery 66 | tracker testing.ObjectTracker 67 | } 68 | 69 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 70 | return c.discovery 71 | } 72 | 73 | func (c *Clientset) Tracker() testing.ObjectTracker { 74 | return c.tracker 75 | } 76 | 77 | var ( 78 | _ clientset.Interface = &Clientset{} 79 | _ testing.FakeClient = &Clientset{} 80 | ) 81 | 82 | // AdmiralV1alpha1 retrieves the AdmiralV1alpha1Client 83 | func (c *Clientset) AdmiralV1alpha1() admiralv1alpha1.AdmiralV1alpha1Interface { 84 | return &fakeadmiralv1alpha1.FakeAdmiralV1alpha1{Fake: &c.Fake} 85 | } 86 | -------------------------------------------------------------------------------- /admiral/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 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/fake/register.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 | admiralv1alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1alpha1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var scheme = runtime.NewScheme() 31 | var codecs = serializer.NewCodecFactory(scheme) 32 | 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | admiralv1alpha1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /admiral/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 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/scheme/register.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 scheme 20 | 21 | import ( 22 | admiralv1alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1alpha1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var Scheme = runtime.NewScheme() 31 | var Codecs = serializer.NewCodecFactory(Scheme) 32 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | admiralv1alpha1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(Scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/model/admiral_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 model 20 | 21 | import ( 22 | "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/model" 23 | "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned/scheme" 24 | "k8s.io/client-go/rest" 25 | ) 26 | 27 | type AdmiralModelInterface interface { 28 | RESTClient() rest.Interface 29 | } 30 | 31 | // AdmiralModelClient is used to interact with features provided by the admiral.io group. 32 | type AdmiralModelClient struct { 33 | restClient rest.Interface 34 | } 35 | 36 | // NewForConfig creates a new AdmiralModelClient for the given config. 37 | func NewForConfig(c *rest.Config) (*AdmiralModelClient, error) { 38 | config := *c 39 | if err := setConfigDefaults(&config); err != nil { 40 | return nil, err 41 | } 42 | client, err := rest.RESTClientFor(&config) 43 | if err != nil { 44 | return nil, err 45 | } 46 | return &AdmiralModelClient{client}, nil 47 | } 48 | 49 | // NewForConfigOrDie creates a new AdmiralModelClient for the given config and 50 | // panics if there is an error in the config. 51 | func NewForConfigOrDie(c *rest.Config) *AdmiralModelClient { 52 | client, err := NewForConfig(c) 53 | if err != nil { 54 | panic(err) 55 | } 56 | return client 57 | } 58 | 59 | // New creates a new AdmiralModelClient for the given RESTClient. 60 | func New(c rest.Interface) *AdmiralModelClient { 61 | return &AdmiralModelClient{c} 62 | } 63 | 64 | func setConfigDefaults(config *rest.Config) error { 65 | gv := model.SchemeGroupVersion 66 | config.GroupVersion = &gv 67 | config.APIPath = "/apis" 68 | config.NegotiatedSerializer = scheme.Codecs 69 | 70 | if config.UserAgent == "" { 71 | config.UserAgent = rest.DefaultKubernetesUserAgent() 72 | } 73 | 74 | return nil 75 | } 76 | 77 | // RESTClient returns a RESTClient that is used to communicate 78 | // with API server by this client implementation. 79 | func (c *AdmiralModelClient) RESTClient() rest.Interface { 80 | if c == nil { 81 | return nil 82 | } 83 | return c.restClient 84 | } 85 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/model/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 model 21 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/model/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 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/model/fake/fake_admiral_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 | rest "k8s.io/client-go/rest" 23 | testing "k8s.io/client-go/testing" 24 | ) 25 | 26 | type FakeAdmiralModel struct { 27 | *testing.Fake 28 | } 29 | 30 | // RESTClient returns a RESTClient that is used to communicate 31 | // with API server by this client implementation. 32 | func (c *FakeAdmiralModel) RESTClient() rest.Interface { 33 | var ret *rest.RESTClient 34 | return ret 35 | } 36 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/model/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 model 20 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/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 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/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 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/v1alpha1/fake/fake_admiral_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 "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned/typed/admiral/v1alpha1" 23 | rest "k8s.io/client-go/rest" 24 | testing "k8s.io/client-go/testing" 25 | ) 26 | 27 | type FakeAdmiralV1alpha1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeAdmiralV1alpha1) ClientConnectionConfigs(namespace string) v1alpha1.ClientConnectionConfigInterface { 32 | return &FakeClientConnectionConfigs{c, namespace} 33 | } 34 | 35 | func (c *FakeAdmiralV1alpha1) Dependencies(namespace string) v1alpha1.DependencyInterface { 36 | return &FakeDependencies{c, namespace} 37 | } 38 | 39 | func (c *FakeAdmiralV1alpha1) GlobalTrafficPolicies(namespace string) v1alpha1.GlobalTrafficPolicyInterface { 40 | return &FakeGlobalTrafficPolicies{c, namespace} 41 | } 42 | 43 | func (c *FakeAdmiralV1alpha1) OutlierDetections(namespace string) v1alpha1.OutlierDetectionInterface { 44 | return &FakeOutlierDetections{c, namespace} 45 | } 46 | 47 | func (c *FakeAdmiralV1alpha1) RoutingPolicies(namespace string) v1alpha1.RoutingPolicyInterface { 48 | return &FakeRoutingPolicies{c, namespace} 49 | } 50 | 51 | func (c *FakeAdmiralV1alpha1) TrafficConfigs(namespace string) v1alpha1.TrafficConfigInterface { 52 | return &FakeTrafficConfigs{c, namespace} 53 | } 54 | 55 | // RESTClient returns a RESTClient that is used to communicate 56 | // with API server by this client implementation. 57 | func (c *FakeAdmiralV1alpha1) RESTClient() rest.Interface { 58 | var ret *rest.RESTClient 59 | return ret 60 | } 61 | -------------------------------------------------------------------------------- /admiral/pkg/client/clientset/versioned/typed/admiral/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 ClientConnectionConfigExpansion interface{} 22 | 23 | type DependencyExpansion interface{} 24 | 25 | type GlobalTrafficPolicyExpansion interface{} 26 | 27 | type OutlierDetectionExpansion interface{} 28 | 29 | type RoutingPolicyExpansion interface{} 30 | 31 | type TrafficConfigExpansion interface{} 32 | -------------------------------------------------------------------------------- /admiral/pkg/client/informers/externalversions/admiral/interface.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 informer-gen. DO NOT EDIT. 18 | 19 | package admiral 20 | 21 | import ( 22 | v1alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/client/informers/externalversions/admiral/v1alpha1" 23 | internalinterfaces "github.com/istio-ecosystem/admiral/admiral/pkg/client/informers/externalversions/internalinterfaces" 24 | ) 25 | 26 | // Interface provides access to each of this group's versions. 27 | type Interface interface { 28 | // V1alpha1 provides access to shared informers for resources in V1alpha1. 29 | V1alpha1() v1alpha1.Interface 30 | } 31 | 32 | type group struct { 33 | factory internalinterfaces.SharedInformerFactory 34 | namespace string 35 | tweakListOptions internalinterfaces.TweakListOptionsFunc 36 | } 37 | 38 | // New returns a new Interface. 39 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 40 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 41 | } 42 | 43 | // V1alpha1 returns a new v1alpha1.Interface. 44 | func (g *group) V1alpha1() v1alpha1.Interface { 45 | return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) 46 | } 47 | -------------------------------------------------------------------------------- /admiral/pkg/client/informers/externalversions/generic.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 informer-gen. DO NOT EDIT. 18 | 19 | package externalversions 20 | 21 | import ( 22 | "fmt" 23 | 24 | v1alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1alpha1" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | cache "k8s.io/client-go/tools/cache" 27 | ) 28 | 29 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 30 | // sharedInformers based on type 31 | type GenericInformer interface { 32 | Informer() cache.SharedIndexInformer 33 | Lister() cache.GenericLister 34 | } 35 | 36 | type genericInformer struct { 37 | informer cache.SharedIndexInformer 38 | resource schema.GroupResource 39 | } 40 | 41 | // Informer returns the SharedIndexInformer. 42 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 43 | return f.informer 44 | } 45 | 46 | // Lister returns the GenericLister. 47 | func (f *genericInformer) Lister() cache.GenericLister { 48 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 49 | } 50 | 51 | // ForResource gives generic access to a shared informer of the matching type 52 | // TODO extend this to unknown resources with a client pool 53 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 54 | switch resource { 55 | // Group=admiral.io, Version=v1alpha1 56 | case v1alpha1.SchemeGroupVersion.WithResource("clientconnectionconfigs"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Admiral().V1alpha1().ClientConnectionConfigs().Informer()}, nil 58 | case v1alpha1.SchemeGroupVersion.WithResource("dependencies"): 59 | return &genericInformer{resource: resource.GroupResource(), informer: f.Admiral().V1alpha1().Dependencies().Informer()}, nil 60 | case v1alpha1.SchemeGroupVersion.WithResource("globaltrafficpolicies"): 61 | return &genericInformer{resource: resource.GroupResource(), informer: f.Admiral().V1alpha1().GlobalTrafficPolicies().Informer()}, nil 62 | case v1alpha1.SchemeGroupVersion.WithResource("outlierdetections"): 63 | return &genericInformer{resource: resource.GroupResource(), informer: f.Admiral().V1alpha1().OutlierDetections().Informer()}, nil 64 | case v1alpha1.SchemeGroupVersion.WithResource("routingpolicies"): 65 | return &genericInformer{resource: resource.GroupResource(), informer: f.Admiral().V1alpha1().RoutingPolicies().Informer()}, nil 66 | case v1alpha1.SchemeGroupVersion.WithResource("trafficconfigs"): 67 | return &genericInformer{resource: resource.GroupResource(), informer: f.Admiral().V1alpha1().TrafficConfigs().Informer()}, nil 68 | 69 | } 70 | 71 | return nil, fmt.Errorf("no informer found for %v", resource) 72 | } 73 | -------------------------------------------------------------------------------- /admiral/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.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 informer-gen. DO NOT EDIT. 18 | 19 | package internalinterfaces 20 | 21 | import ( 22 | time "time" 23 | 24 | versioned "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned" 25 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | cache "k8s.io/client-go/tools/cache" 28 | ) 29 | 30 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 31 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 32 | 33 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 34 | type SharedInformerFactory interface { 35 | Start(stopCh <-chan struct{}) 36 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 37 | } 38 | 39 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 40 | type TweakListOptionsFunc func(*v1.ListOptions) 41 | -------------------------------------------------------------------------------- /admiral/pkg/client/listers/admiral/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 | // ClientConnectionConfigListerExpansion allows custom methods to be added to 22 | // ClientConnectionConfigLister. 23 | type ClientConnectionConfigListerExpansion interface{} 24 | 25 | // ClientConnectionConfigNamespaceListerExpansion allows custom methods to be added to 26 | // ClientConnectionConfigNamespaceLister. 27 | type ClientConnectionConfigNamespaceListerExpansion interface{} 28 | 29 | // DependencyListerExpansion allows custom methods to be added to 30 | // DependencyLister. 31 | type DependencyListerExpansion interface{} 32 | 33 | // DependencyNamespaceListerExpansion allows custom methods to be added to 34 | // DependencyNamespaceLister. 35 | type DependencyNamespaceListerExpansion interface{} 36 | 37 | // GlobalTrafficPolicyListerExpansion allows custom methods to be added to 38 | // GlobalTrafficPolicyLister. 39 | type GlobalTrafficPolicyListerExpansion interface{} 40 | 41 | // GlobalTrafficPolicyNamespaceListerExpansion allows custom methods to be added to 42 | // GlobalTrafficPolicyNamespaceLister. 43 | type GlobalTrafficPolicyNamespaceListerExpansion interface{} 44 | 45 | // OutlierDetectionListerExpansion allows custom methods to be added to 46 | // OutlierDetectionLister. 47 | type OutlierDetectionListerExpansion interface{} 48 | 49 | // OutlierDetectionNamespaceListerExpansion allows custom methods to be added to 50 | // OutlierDetectionNamespaceLister. 51 | type OutlierDetectionNamespaceListerExpansion interface{} 52 | 53 | // RoutingPolicyListerExpansion allows custom methods to be added to 54 | // RoutingPolicyLister. 55 | type RoutingPolicyListerExpansion interface{} 56 | 57 | // RoutingPolicyNamespaceListerExpansion allows custom methods to be added to 58 | // RoutingPolicyNamespaceLister. 59 | type RoutingPolicyNamespaceListerExpansion interface{} 60 | 61 | // TrafficConfigListerExpansion allows custom methods to be added to 62 | // TrafficConfigLister. 63 | type TrafficConfigListerExpansion interface{} 64 | 65 | // TrafficConfigNamespaceListerExpansion allows custom methods to be added to 66 | // TrafficConfigNamespaceLister. 67 | type TrafficConfigNamespaceListerExpansion interface{} 68 | -------------------------------------------------------------------------------- /admiral/pkg/client/loader/client_loader.go: -------------------------------------------------------------------------------- 1 | package loader 2 | 3 | import ( 4 | argo "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned" 5 | admiralapi "github.com/istio-ecosystem/admiral-api/pkg/client/clientset/versioned" 6 | admiral "github.com/istio-ecosystem/admiral/admiral/pkg/client/clientset/versioned" 7 | numaflow "github.com/numaproj/numaflow/pkg/client/clientset/versioned" 8 | istio "istio.io/client-go/pkg/clientset/versioned" 9 | "k8s.io/client-go/kubernetes" 10 | "k8s.io/client-go/rest" 11 | ) 12 | 13 | const FakeKubeconfigPath = "fake.config" 14 | 15 | type ClientLoader interface { 16 | LoadAdmiralClientFromPath(path string) (admiral.Interface, error) 17 | LoadAdmiralClientFromConfig(config *rest.Config) (admiral.Interface, error) 18 | 19 | LoadAdmiralApiClientFromPath(path string) (admiralapi.Interface, error) 20 | LoadAdmiralApiClientFromConfig(config *rest.Config) (admiralapi.Interface, error) 21 | 22 | LoadIstioClientFromPath(path string) (istio.Interface, error) 23 | LoadIstioClientFromConfig(config *rest.Config) (istio.Interface, error) 24 | 25 | LoadArgoClientFromPath(path string) (argo.Interface, error) 26 | LoadArgoClientFromConfig(config *rest.Config) (argo.Interface, error) 27 | 28 | LoadKubeClientFromPath(path string) (kubernetes.Interface, error) 29 | LoadKubeClientFromConfig(config *rest.Config) (kubernetes.Interface, error) 30 | 31 | LoadNumaflowClientFromPath(path string) (numaflow.Interface, error) 32 | LoadNumaflowClientFromConfig(config *rest.Config) (numaflow.Interface, error) 33 | } 34 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/admiralStateChecker.go: -------------------------------------------------------------------------------- 1 | package clusters 2 | 3 | // admiralStateChecker.go 4 | 5 | import ( 6 | "context" 7 | commonUtil "github.com/istio-ecosystem/admiral/admiral/pkg/util" 8 | "strings" 9 | 10 | log "github.com/sirupsen/logrus" 11 | ) 12 | 13 | type AdmiralStateChecker interface { 14 | runStateCheck(ctx context.Context) 15 | shouldRunOnIndependentGoRoutine() bool 16 | initStateCache(interface{}) error 17 | } 18 | 19 | /* 20 | Utility function to start Admiral DR checks. 21 | DR checks can be run either on the main go routine or a new go routine 22 | */ 23 | func RunAdmiralStateCheck(ctx context.Context, stateChecker string, asc AdmiralStateChecker) { 24 | if asc.shouldRunOnIndependentGoRoutine() { 25 | go asc.runStateCheck(ctx) 26 | } else { 27 | asc.runStateCheck(ctx) 28 | } 29 | } 30 | 31 | /* 32 | utility function to identify the Admiral DR implementation based on the program parameters 33 | */ 34 | func initAdmiralStateChecker(ctx context.Context, stateChecker string, stateConfigFilePath string) AdmiralStateChecker { 35 | log.Printf("starting state checker for: %s", stateChecker) 36 | var admiralStateChecker AdmiralStateChecker 37 | var err error 38 | switch strings.ToLower(stateChecker) { 39 | // Add entries for your custom Disaster Recovery state checkers below 40 | // case "checker": 41 | // admiralStateChecker = customChecker{} 42 | case ignoreIdentityChecker: 43 | admiralStateChecker, err = NewIgnoreIdentityStateChecker(stateConfigFilePath, NewDynamoClient) 44 | if err != nil { 45 | log.Fatalf("failed to configure %s state checker, err: %v", ignoreIdentityChecker, err) 46 | } 47 | case drStateChecker: 48 | admiralStateChecker = admiralReadWriteLeaseStateChecker{stateConfigFilePath} 49 | default: 50 | admiralStateChecker = NoOPStateChecker{} 51 | } 52 | return admiralStateChecker 53 | } 54 | 55 | /* 56 | Default implementation of the interface defined for DR 57 | */ 58 | type NoOPStateChecker struct{} 59 | 60 | func (NoOPStateChecker) shouldRunOnIndependentGoRoutine() bool { 61 | return false 62 | } 63 | 64 | func (NoOPStateChecker) initStateCache(cache interface{}) error { 65 | return nil 66 | } 67 | 68 | func (NoOPStateChecker) runStateCheck(ctx context.Context) { 69 | log.Info("NoOP State Checker called. Marking Admiral state as Read/Write enabled") 70 | commonUtil.CurrentAdmiralState.ReadOnly = ReadWriteEnabled 71 | commonUtil.CurrentAdmiralState.IsStateInitialized = StateInitialized 72 | } 73 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/clusters.go: -------------------------------------------------------------------------------- 1 | package clusters 2 | 3 | const ( 4 | ReadWriteEnabled = false 5 | ReadOnlyEnabled = true 6 | StateNotInitialized = false 7 | StateInitialized = true 8 | ignoreIdentityChecker = "dynamodbbasedignoreidentitylistchecker" 9 | drStateChecker = "dynamodbbasedstatechecker" 10 | AdmiralLeaseTableName = "admiral-lease" 11 | ) 12 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/metrics.go: -------------------------------------------------------------------------------- 1 | package clusters 2 | 3 | import "github.com/istio-ecosystem/admiral/admiral/pkg/monitoring" 4 | 5 | // List all metrics part of the clusters package here 6 | var ( 7 | configWriterMeter = monitoring.NewMeter("config_writer") 8 | totalConfigWriterEvents = monitoring.NewCounter( 9 | "total_config_write_invocations", 10 | "total number of times config writer was invoked", 11 | monitoring.WithMeter(configWriterMeter)) 12 | ) 13 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/mocks_test.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.43.2. DO NOT EDIT. 2 | package clusters 3 | 4 | import ( 5 | context "context" 6 | logrus "github.com/sirupsen/logrus" 7 | mock "github.com/stretchr/testify/mock" 8 | v1alpha3 "istio.io/api/networking/v1alpha3" 9 | ) 10 | 11 | // ConfigWriter is an autogenerated mock type for the ConfigWriter type 12 | type ConfigWriterMock struct { 13 | mock.Mock 14 | } 15 | 16 | // AddServiceEntriesWithDrToAllCluster provides a mock function with given fields: ctxLogger, ctx, rr, sourceClusters, serviceEntries, isAdditionalEndpointsEnabled, isServiceEntryModifyCalledForSourceCluster, identityId, env 17 | func (_m *ConfigWriterMock) AddServiceEntriesWithDrToAllCluster(ctxLogger *logrus.Entry, ctx context.Context, rr *RemoteRegistry, sourceClusters map[string]string, serviceEntries map[string]*v1alpha3.ServiceEntry, isAdditionalEndpointsEnabled bool, isServiceEntryModifyCalledForSourceCluster bool, identityId string, env string) error { 18 | ret := _m.Called(ctxLogger, ctx, rr, sourceClusters, serviceEntries, isAdditionalEndpointsEnabled, isServiceEntryModifyCalledForSourceCluster, identityId, env) 19 | 20 | if len(ret) == 0 { 21 | panic("no return value specified for AddServiceEntriesWithDrToAllCluster") 22 | } 23 | 24 | var r0 error 25 | if rf, ok := ret.Get(0).(func(*logrus.Entry, context.Context, *RemoteRegistry, map[string]string, map[string]*v1alpha3.ServiceEntry, bool, bool, string, string) error); ok { 26 | r0 = rf(ctxLogger, ctx, rr, sourceClusters, serviceEntries, isAdditionalEndpointsEnabled, isServiceEntryModifyCalledForSourceCluster, identityId, env) 27 | } else { 28 | r0 = ret.Error(0) 29 | } 30 | 31 | return r0 32 | } 33 | 34 | // NewConfigWriter creates a new instance of ConfigWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 35 | // The first argument is typically a *testing.T value. 36 | func NewConfigWriterMock(t interface { 37 | mock.TestingT 38 | Cleanup(func()) 39 | }) *ConfigWriterMock { 40 | mock := &ConfigWriterMock{} 41 | mock.Mock.Test(t) 42 | t.Cleanup(func() { mock.AssertExpectations(t) }) 43 | return mock 44 | } 45 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/sidecar_handler.go: -------------------------------------------------------------------------------- 1 | package clusters 2 | 3 | import ( 4 | "context" 5 | 6 | "istio.io/client-go/pkg/apis/networking/v1alpha3" 7 | ) 8 | 9 | // SidecarHandler responsible for handling Add/Update/Delete events for 10 | // Sidecar resources 11 | type SidecarHandler struct { 12 | RemoteRegistry *RemoteRegistry 13 | ClusterID string 14 | } 15 | 16 | func (dh *SidecarHandler) Added(ctx context.Context, obj *v1alpha3.Sidecar) error { 17 | return nil 18 | } 19 | 20 | func (dh *SidecarHandler) Updated(ctx context.Context, obj *v1alpha3.Sidecar) error { 21 | return nil 22 | } 23 | 24 | func (dh *SidecarHandler) Deleted(ctx context.Context, obj *v1alpha3.Sidecar) error { 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/sidecar_handler_test.go: -------------------------------------------------------------------------------- 1 | package clusters 2 | 3 | import ( 4 | "context" 5 | "github.com/stretchr/testify/assert" 6 | "istio.io/client-go/pkg/apis/networking/v1alpha3" 7 | "testing" 8 | ) 9 | 10 | func TestSidecarHandler_Added(t *testing.T) { 11 | var dh SidecarHandler 12 | var ctx context.Context 13 | var obj *v1alpha3.Sidecar 14 | err := dh.Added(ctx, obj) 15 | assert.Nil(t, err) 16 | } 17 | 18 | func TestSidecarHandler_Updated(t *testing.T) { 19 | var dh SidecarHandler 20 | var ctx context.Context 21 | var obj *v1alpha3.Sidecar 22 | err := dh.Updated(ctx, obj) 23 | assert.Nil(t, err) 24 | } 25 | 26 | func TestSidecarHandler_Deleted(t *testing.T) { 27 | var dh SidecarHandler 28 | var ctx context.Context 29 | var obj *v1alpha3.Sidecar 30 | err := dh.Deleted(ctx, obj) 31 | assert.Nil(t, err) 32 | } 33 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralDatabaseClientConfig_invalid.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | region: "us-east-2" 5 | role: "arn:aws:iam::1111111:role/Admiral-IKS-Dynamo-Read-Access" 6 | tableName: "admiral-ignore-identity-state" 7 | clusterEnvironment: "dev" 8 | dynamoDB: 9 | leaseName: qal 10 | podIdentifier: qal-east 11 | waitTimeInSeconds: 15 12 | failureThreshold: 3 13 | tableName: admiral-lease 14 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 15 | region: us-east-2 16 | database: 17 | region: "us-west-2" 18 | role: "arn:aws:iam::11111111:role/Admiral-IKS-Dynamo-Read-Write-Access" 19 | workloadDataTableName: admiral-workload-data-dev 20 | testField: "testValue" -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralDatabaseClientConfig_is_valid.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | region: "us-east-2" 5 | role: "arn:aws:iam::1111111:role/Admiral-IKS-Dynamo-Read-Access" 6 | tableName: "admiral-ignore-identity-state" 7 | clusterEnvironment: "dev" 8 | dynamoDB: 9 | leaseName: qal 10 | podIdentifier: qal-east 11 | waitTimeInSeconds: 15 12 | failureThreshold: 3 13 | tableName: admiral-lease 14 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 15 | region: us-east-2 16 | database: 17 | region: "us-west-2" 18 | role: "arn:aws:iam::11111111:role/Admiral-IKS-Dynamo-Read-Write-Access" 19 | workloadDataTableName: admiral-workload-data-dev -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_admiralConfig_is_nil.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_admiralConfig_is_nil.yaml -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_admiralConfig_is_valid.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | region: "us-east-2" 5 | role: "arn:aws:iam::1111111:role/Admiral-IKS-Dynamo-Read-Access" 6 | tableName: "admiral-ignore-identity-state" 7 | clusterEnvironment: "dev" 8 | dynamoDB: 9 | leaseName: qal 10 | podIdentifier: qal-east 11 | waitTimeInSeconds: 15 12 | failureThreshold: 3 13 | tableName: admiral-lease 14 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 15 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.StateCheckPeriod_is_0.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.StateCheckPeriod_is_0.yaml -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.ClusterEnvironment_is_empty.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | region: "us-east-2" 5 | role: "arn:aws:iam::1111111:role/Admiral-IKS-Dynamo-Read-Access" 6 | tableName: "admiral-ignore-identity-state" 7 | clusterEnvironment: "" 8 | dynamoDB: 9 | leaseName: qal 10 | podIdentifier: qal-east 11 | waitTimeInSeconds: 15 12 | failureThreshold: 3 13 | tableName: admiral-lease 14 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 15 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.Region_is_empty.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | role: "arn:aws:iam::1111111:role/Admiral-IKS-Dynamo-Read-Access" 5 | tableName: "test-db-1" 6 | clusterEnvironment: "dev" 7 | dynamoDB: 8 | leaseName: qal 9 | podIdentifier: qal-east 10 | waitTimeInSeconds: 15 11 | failureThreshold: 3 12 | tableName: admiral-lease 13 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 14 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.Role_is_empty.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | region: "us-east-2" 5 | tableName: "test-db-1" 6 | clusterEnvironment: "dev" 7 | dynamoDB: 8 | leaseName: qal 9 | podIdentifier: qal-east 10 | waitTimeInSeconds: 15 11 | failureThreshold: 3 12 | tableName: admiral-lease 13 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 14 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB.TableName_is_empty.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | region: "us-east-2" 5 | role: "arn:aws:iam::1111111:role/Admiral-IKS-Dynamo-Read-Access" 6 | clusterEnvironment: "dev" 7 | dynamoDB: 8 | leaseName: qal 9 | podIdentifier: qal-east 10 | waitTimeInSeconds: 15 11 | failureThreshold: 3 12 | tableName: admiral-lease 13 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 14 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList.dynamoDB_is_empty.yaml: -------------------------------------------------------------------------------- 1 | ignoreIdentityList: 2 | stateCheckerPeriodInSeconds: 60 3 | dynamoDB: 4 | leaseName: qal 5 | podIdentifier: qal-east 6 | waitTimeInSeconds: 15 7 | failureThreshold: 3 8 | tableName: admiral-lease 9 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 10 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/admiralIgnoreIdentityStateChecker_ignoreIdentityList_is_empty.yaml: -------------------------------------------------------------------------------- 1 | dynamoDB: 2 | leaseName: qal 3 | podIdentifier: qal-east 4 | waitTimeInSeconds: 15 5 | failureThreshold: 3 6 | tableName: admiral-lease 7 | role: arn:aws:iam::11111111:role/Admiral-IKS-Access 8 | region: us-east-2 -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/expectedIdentityIdentityConfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityName": "identity", 3 | "clusters": { 4 | "test-dev-k8s": { 5 | "name": "test-dev-k8s", 6 | "locality": "us-west-2", 7 | "ingressEndpoint": "east.aws.lb", 8 | "ingressPort": "15443", 9 | "ingressPortName": "http", 10 | "environment": { 11 | "test": { 12 | "name": "test", 13 | "namespace": "foobar-ns", 14 | "services": { 15 | "default": [ 16 | { 17 | "name": "foobar", 18 | "ports": { 19 | "http": 8090 20 | }, 21 | "selectors": { 22 | "app": "identity" 23 | } 24 | }, 25 | { 26 | "name": "foobar-stable", 27 | "ports": { 28 | "http": 8090 29 | }, 30 | "selectors": { 31 | "app": "identity" 32 | } 33 | } 34 | ] 35 | }, 36 | "serviceName": "", 37 | "type": { 38 | "rollout": { 39 | "strategy": "", 40 | "selectors": { 41 | "app": "identity", 42 | "identity": "identity" 43 | } 44 | } 45 | }, 46 | "ports": [ 47 | { 48 | "number": 80, 49 | "protocol": "http", 50 | "name": "http" 51 | } 52 | ], 53 | "trafficPolicy": { 54 | "globaltrafficpolicy": { 55 | "metadata": { 56 | "creationTimestamp": null 57 | }, 58 | "spec": {}, 59 | "status": { 60 | "clustersSynced": 0, 61 | "state": "" 62 | } 63 | }, 64 | "outlierdetection": { 65 | "metadata": { 66 | "creationTimestamp": null 67 | }, 68 | "spec": {}, 69 | "status": { 70 | "clustersSynced": 0, 71 | "state": "" 72 | } 73 | }, 74 | "clientconnectionconfig": { 75 | "metadata": { 76 | "creationTimestamp": null 77 | }, 78 | "spec": { 79 | "connectionPool": {}, 80 | "tunnel": {} 81 | }, 82 | "status": { 83 | "state": "" 84 | } 85 | } 86 | }, 87 | "event": "" 88 | } 89 | } 90 | } 91 | }, 92 | "clientAssets": null 93 | } -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/fake.config: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | 5 | server: https://192.168.99.121:8443 6 | name: kube 7 | contexts: 8 | - context: 9 | cluster: kube 10 | user: kube 11 | name: kube 12 | current-context: kube 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: kube 17 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/fake_2.config: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | 5 | server: https://192.168.99.122:8443 #different server address 6 | name: kube 7 | contexts: 8 | - context: 9 | cluster: kube 10 | user: kube 11 | name: kube 12 | current-context: kube 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: kube 17 | -------------------------------------------------------------------------------- /admiral/pkg/clusters/testdata/identityIdentityConfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityName": "identity", 3 | "clusters": { 4 | "test-dev-k8s": { 5 | "name": "test-dev-k8s", 6 | "locality": "us-west-2", 7 | "ingressEndpoint": "east.aws.lb", 8 | "ingressPort": "15443", 9 | "ingressPortName": "http", 10 | "environment": { 11 | "test": { 12 | "name": "test", 13 | "namespace": "foobar-ns", 14 | "services": { 15 | "default": [ 16 | { 17 | "name": "foobar", 18 | "ports": { 19 | "http": 8090 20 | }, 21 | "selectors": { 22 | "app": "identity" 23 | } 24 | }, 25 | { 26 | "name": "foobar-stable", 27 | "ports": { 28 | "http": 8090 29 | }, 30 | "selectors": { 31 | "app": "identity" 32 | } 33 | } 34 | ] 35 | }, 36 | "serviceName": "", 37 | "type": { 38 | "rollout": { 39 | "strategy": "", 40 | "selectors": { 41 | "app": "identity", 42 | "identity": "identity" 43 | } 44 | } 45 | }, 46 | "ports": [ 47 | { 48 | "number": 80, 49 | "protocol": "http", 50 | "name": "http" 51 | } 52 | ], 53 | "trafficPolicy": { 54 | "globaltrafficpolicy": { 55 | "metadata": { 56 | "creationTimestamp": null 57 | }, 58 | "spec": {}, 59 | "status": { 60 | "clustersSynced": 0, 61 | "state": "" 62 | } 63 | }, 64 | "outlierdetection": { 65 | "metadata": { 66 | "creationTimestamp": null 67 | }, 68 | "spec": {}, 69 | "status": { 70 | "clustersSynced": 0, 71 | "state": "" 72 | } 73 | }, 74 | "clientconnectionconfig": { 75 | "metadata": { 76 | "creationTimestamp": null 77 | }, 78 | "spec": { 79 | "connectionPool": {}, 80 | "tunnel": {} 81 | }, 82 | "status": { 83 | "state": "" 84 | } 85 | } 86 | }, 87 | "event": "" 88 | } 89 | } 90 | } 91 | }, 92 | "clientAssets": null 93 | } -------------------------------------------------------------------------------- /admiral/pkg/clusters/types_test.go: -------------------------------------------------------------------------------- 1 | package clusters 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "sync" 6 | "testing" 7 | "time" 8 | 9 | "github.com/google/go-cmp/cmp/cmpopts" 10 | admiralV1 "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1alpha1" 11 | 12 | "github.com/istio-ecosystem/admiral/admiral/pkg/controller/common" 13 | ) 14 | 15 | var ignoreUnexported = cmpopts.IgnoreUnexported(admiralV1.GlobalTrafficPolicy{}.Status) 16 | 17 | var typeTestSingleton sync.Once 18 | 19 | func admiralParamsForTypesTests() common.AdmiralParams { 20 | return common.AdmiralParams{ 21 | KubeconfigPath: "testdata/fake.config", 22 | LabelSet: &common.LabelSet{ 23 | WorkloadIdentityKey: "identity", 24 | EnvKey: "admiral.io/env", 25 | AdmiralCRDIdentityLabel: "identity", 26 | PriorityKey: "priority", 27 | }, 28 | EnableSAN: true, 29 | SANPrefix: "prefix", 30 | HostnameSuffix: "mesh", 31 | SyncNamespace: "ns", 32 | CacheReconcileDuration: time.Minute, 33 | ClusterRegistriesNamespace: "default", 34 | DependenciesNamespace: "default", 35 | EnableRoutingPolicy: true, 36 | EnvoyFilterVersion: "1.13", 37 | Profile: common.AdmiralProfileDefault, 38 | } 39 | } 40 | 41 | func setupForTypeTests() { 42 | typeTestSingleton.Do(func() { 43 | common.ResetSync() 44 | common.InitializeConfig(admiralParamsForTypesTests()) 45 | }) 46 | } 47 | 48 | func TestRangeRemoteControllers(t *testing.T) { 49 | setupForTypeTests() 50 | 51 | rr := &RemoteRegistry{ 52 | Mutex: sync.Mutex{}, 53 | remoteControllers: map[string]*RemoteController{"test": &RemoteController{}}, 54 | } 55 | 56 | counter := 0 57 | // testFunc is a function that tests the RemoteController 58 | testFunc := func(k string, v *RemoteController) { 59 | counter = counter + 1 60 | } 61 | 62 | // TestRangeRemoteControllers is a table-driven test for RangeRemoteControllers 63 | tests := []struct { 64 | name string 65 | expected int 66 | }{ 67 | { 68 | name: "TestRangeRemoteControllers", 69 | expected: 1, 70 | }, 71 | } 72 | for _, tt := range tests { 73 | counter = 0 74 | t.Run(tt.name, func(t *testing.T) { 75 | rr.RangeRemoteControllers(testFunc) 76 | assert.Equal(t, tt.expected, counter) 77 | }) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /admiral/pkg/controller/admiral/configmap.go: -------------------------------------------------------------------------------- 1 | package admiral 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "github.com/istio-ecosystem/admiral/admiral/pkg/client/loader" 8 | "github.com/istio-ecosystem/admiral/admiral/pkg/controller/common" 9 | v1 "k8s.io/api/core/v1" 10 | metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | "k8s.io/client-go/kubernetes" 12 | ) 13 | 14 | type ConfigMapControllerInterface interface { 15 | GetConfigMap(ctx context.Context) (*v1.ConfigMap, error) 16 | PutConfigMap(ctx context.Context, newMap *v1.ConfigMap) error 17 | GetIPPrefixForServiceEntries() (seIPPrefix string) 18 | } 19 | 20 | type ConfigMapController struct { 21 | K8sClient kubernetes.Interface 22 | ConfigmapNamespace string 23 | ServiceEntryIPPrefix string 24 | } 25 | 26 | // todo this is a temp state, eventually changes will have to be made to give each cluster it's own configmap 27 | func NewConfigMapController(seIPPrefix string, clientLoader loader.ClientLoader) (*ConfigMapController, error) { 28 | kubeconfigPath := common.GetKubeconfigPath() 29 | namespaceToUse := common.GetSyncNamespace() 30 | 31 | client, err := clientLoader.LoadKubeClientFromPath(kubeconfigPath) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | controller := ConfigMapController{ 37 | K8sClient: client, 38 | ConfigmapNamespace: namespaceToUse, 39 | ServiceEntryIPPrefix: seIPPrefix, 40 | } 41 | 42 | return &controller, nil 43 | } 44 | 45 | func (c *ConfigMapController) GetConfigMap(ctx context.Context) (*v1.ConfigMap, error) { 46 | getOpts := metaV1.GetOptions{} 47 | configMap, err := c.K8sClient.CoreV1().ConfigMaps(c.ConfigmapNamespace).Get(ctx, common.GetSeAddressConfigMap(), getOpts) 48 | 49 | if err == nil { 50 | return configMap, err 51 | } 52 | 53 | if strings.Contains(err.Error(), "not found") { 54 | cm := v1.ConfigMap{} 55 | cm.Name = common.GetSeAddressConfigMap() 56 | cm.Namespace = c.ConfigmapNamespace 57 | configMap, err = c.K8sClient.CoreV1().ConfigMaps(c.ConfigmapNamespace).Create(ctx, &cm, metaV1.CreateOptions{}) 58 | } 59 | 60 | return configMap, err 61 | 62 | } 63 | 64 | func (c *ConfigMapController) PutConfigMap(ctx context.Context, newMap *v1.ConfigMap) error { 65 | _, err := c.K8sClient.CoreV1().ConfigMaps(c.ConfigmapNamespace).Update(ctx, newMap, metaV1.UpdateOptions{}) 66 | return err 67 | } 68 | 69 | func (c *ConfigMapController) GetIPPrefixForServiceEntries() string { 70 | return c.ServiceEntryIPPrefix 71 | } 72 | -------------------------------------------------------------------------------- /admiral/pkg/controller/admiral/delegator_mock_test.go: -------------------------------------------------------------------------------- 1 | package admiral 2 | 3 | import ( 4 | "context" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | type MockDelegator struct { 10 | obj interface{} 11 | getErr error 12 | } 13 | 14 | func (m *MockDelegator) DoesGenerationMatch(ctx *log.Entry, i interface{}, i2 interface{}) (bool, error) { 15 | return false, nil 16 | } 17 | 18 | func (m *MockDelegator) IsOnlyReplicaCountChanged(ctx *log.Entry, i interface{}, i2 interface{}) (bool, error) { 19 | return false, nil 20 | } 21 | 22 | func NewMockDelegator() *MockDelegator { 23 | return &MockDelegator{} 24 | } 25 | 26 | func (m *MockDelegator) SetGetReturn(obj interface{}, err error) { 27 | m.obj = obj 28 | m.getErr = err 29 | } 30 | 31 | func (m *MockDelegator) Added(context.Context, interface{}) error { 32 | return nil 33 | } 34 | func (m *MockDelegator) Updated(context.Context, interface{}, interface{}) error { 35 | return nil 36 | } 37 | func (m *MockDelegator) Deleted(context.Context, interface{}) error { 38 | return nil 39 | } 40 | func (m *MockDelegator) UpdateProcessItemStatus(interface{}, string) error { 41 | return nil 42 | } 43 | func (m *MockDelegator) GetProcessItemStatus(interface{}) (string, error) { 44 | return "", nil 45 | } 46 | func (m *MockDelegator) LogValueOfAdmiralIoIgnore(interface{}) { 47 | return 48 | } 49 | func (m *MockDelegator) Get(context.Context, bool, interface{}) (interface{}, error) { 50 | return m.obj, m.getErr 51 | } 52 | -------------------------------------------------------------------------------- /admiral/pkg/controller/admiral/util_test.go: -------------------------------------------------------------------------------- 1 | package admiral 2 | 3 | import "strings" 4 | 5 | func ErrorEqualOrSimilar(err1, err2 error) bool { 6 | if err1 != nil && err2 == nil { 7 | return false 8 | } 9 | if err1 != nil && err2 != nil { 10 | if !(err1.Error() == err2.Error() || 11 | strings.Contains(err1.Error(), err2.Error())) { 12 | return false 13 | } 14 | } 15 | if err1 == nil && err2 != nil { 16 | return false 17 | } 18 | return true 19 | } 20 | -------------------------------------------------------------------------------- /admiral/pkg/controller/common/cache.go: -------------------------------------------------------------------------------- 1 | package common 2 | -------------------------------------------------------------------------------- /admiral/pkg/controller/common/metrics.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import "github.com/prometheus/client_golang/prometheus" 4 | 5 | const ClustersMonitoredMetricName = "clusters_monitored" 6 | const DependencyProxyServiceCacheSizeMetricName = "dependency_proxy_service_cache_size" 7 | 8 | type Gauge interface { 9 | Set(value float64) 10 | } 11 | 12 | func NewGaugeFrom(name string, help string) Gauge { 13 | if !GetMetricsEnabled() { 14 | return &Noop{} 15 | } 16 | opts := prometheus.GaugeOpts{Name: name, Help: help} 17 | g := prometheus.NewGauge(opts) 18 | prometheus.MustRegister(g) 19 | return &PromGauge{g} 20 | } 21 | 22 | type Noop struct{} 23 | 24 | type PromGauge struct { 25 | g prometheus.Gauge 26 | } 27 | 28 | func (g *PromGauge) Set(value float64) { 29 | g.g.Set(value) 30 | } 31 | 32 | func (g *Noop) Set(value float64) {} 33 | -------------------------------------------------------------------------------- /admiral/pkg/controller/common/metrics_test.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestNewGaugeFrom(t *testing.T) { 11 | type args struct { 12 | prom bool 13 | Name string 14 | Help string 15 | } 16 | tc := []struct { 17 | name string 18 | args args 19 | want Gauge 20 | }{ 21 | { 22 | "Should return a Prometheus gauge", 23 | args{true, "gauge", ""}, 24 | &PromGauge{prometheus.NewGauge(prometheus.GaugeOpts{Name: "gauge", Help: ""})}, 25 | }, 26 | { 27 | "Should return a Noop gauge", 28 | args{false, "gauge", ""}, 29 | &Noop{}, 30 | }, 31 | } 32 | 33 | for _, tt := range tc { 34 | t.Run(tt.name, func(t *testing.T) { 35 | SetEnablePrometheus(tt.args.prom) 36 | actual := NewGaugeFrom(tt.args.Name, tt.args.Help) 37 | assert.Equal(t, tt.want, actual, "want: %#v, got: %#v", tt.want, actual) 38 | }) 39 | } 40 | } 41 | 42 | func TestNoop_Set(t *testing.T) { 43 | n := Noop{} 44 | n.Set(1) 45 | } 46 | -------------------------------------------------------------------------------- /admiral/pkg/controller/secret/resolver/defaultresolver.go: -------------------------------------------------------------------------------- 1 | package resolver 2 | 3 | //The default resolver uses the k8s secret payload to be the valid kubeconfig for the remote cluster 4 | 5 | func (r DefaultResolver) FetchKubeConfig(secretName string, kubeConfig []byte) ([]byte, error) { 6 | return kubeConfig, nil 7 | } 8 | 9 | type DefaultResolver struct { 10 | } 11 | 12 | func (r DefaultResolver) DeleteClusterFromCache(clusterName string) error { 13 | return nil 14 | } 15 | 16 | func NewDefaultResolver() (SecretResolver, error) { 17 | resolver := DefaultResolver{} 18 | return resolver, nil 19 | } 20 | -------------------------------------------------------------------------------- /admiral/pkg/controller/secret/resolver/defaultresolver_test.go: -------------------------------------------------------------------------------- 1 | package resolver 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestNewDefaultResolver(t *testing.T) { 10 | resolver, err := NewDefaultResolver() 11 | assert.NotNil(t, resolver, "DefaultResolver should not be nil") 12 | assert.Nil(t, err, "Error while new instance creation should be nil") 13 | } 14 | 15 | func TestDefaultResolver_FetchKubeConfig(t *testing.T) { 16 | expectedKubeConfig := ` 17 | apiVersion: v1 18 | clusters: 19 | - cluster: 20 | certificate-authority-data: ca_data 21 | server: https://example.com 22 | name: example-cluster 23 | contexts: 24 | - context: 25 | cluster: example-cluster 26 | user: example-user 27 | name: example-context 28 | current-context: example-context 29 | kind: Config 30 | preferences: {} 31 | users: 32 | - name: example-user 33 | user: 34 | client-certificate-data: cert_data 35 | client-key-data: key_data 36 | ` 37 | resolver, _ := NewDefaultResolver() 38 | kconfig, err := resolver.FetchKubeConfig("", []byte(expectedKubeConfig)) 39 | assert.Equal(t, []byte(expectedKubeConfig), kconfig) 40 | assert.Nil(t, err, "Expected error to be nil") 41 | } 42 | -------------------------------------------------------------------------------- /admiral/pkg/controller/secret/resolver/resolver.go: -------------------------------------------------------------------------------- 1 | package resolver 2 | 3 | // Interface for fetching kubeconfig of a remote cluster from k8s secret 4 | 5 | type SecretResolver interface { 6 | FetchKubeConfig(secretName string, kubeConfig []byte) ([]byte, error) 7 | DeleteClusterFromCache(clusterName string) error 8 | } 9 | -------------------------------------------------------------------------------- /admiral/pkg/controller/util/migration.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/istio-ecosystem/admiral/admiral/pkg/controller/common" 7 | networking "istio.io/api/networking/v1alpha3" 8 | k8sV1 "k8s.io/api/core/v1" 9 | ) 10 | 11 | // UpdateEndpointsForDeployToRolloutMigration creates an SE with the endpoints for both the rollout and deployment 12 | // This is for Deployment <-> Rollout migration 13 | func UpdateEndpointsForDeployToRolloutMigration(serviceInstance map[string]*k8sV1.Service, 14 | serviceEntry *networking.ServiceEntry, meshPorts map[string]map[string]uint32, clusterIngress string, 15 | clusterAppDeleteMap map[string]string, clusterName string, 16 | clusterDeployRolloutPresent map[string]map[string]bool) ([]*k8sV1.Service, error) { 17 | if serviceInstance[common.Deployment] == nil || serviceInstance[common.Rollout] == nil { 18 | return nil, fmt.Errorf("serviceInstance for Deployment/Rollout is nil as the service cache has not updated yet") 19 | } 20 | 21 | deployLocalFqdn := serviceInstance[common.Deployment].Name + common.Sep + serviceInstance[common.Deployment].Namespace + common.GetLocalDomainSuffix() 22 | rolloutFqdn := serviceInstance[common.Rollout].Name + common.Sep + serviceInstance[common.Rollout].Namespace + common.GetLocalDomainSuffix() 23 | var requiredServices []*k8sV1.Service 24 | 25 | var uniqueEndpointsList []*networking.WorkloadEntry 26 | for _, ep := range serviceEntry.Endpoints { 27 | // only if the ep.Address is equal to clusterIngress do we append the deployment 28 | // and rollout endpoint for add and update events. 29 | // For delete events we check for which cluster did we get the event for and then 30 | // decide which cluster to remove the deployment or rollout endpoint for. 31 | if ep.Address == clusterIngress { 32 | if clusterAppDeleteMap[clusterName] != common.Deployment && clusterDeployRolloutPresent[clusterName][common.Deployment] { 33 | deployEp := &networking.WorkloadEntry{ 34 | Address: deployLocalFqdn, 35 | Locality: ep.Locality, 36 | Ports: meshPorts[common.Deployment], 37 | Labels: map[string]string{"type": common.Deployment, "security.istio.io/tlsMode": "istio"}, 38 | } 39 | uniqueEndpointsList = append(uniqueEndpointsList, deployEp) 40 | requiredServices = append(requiredServices, serviceInstance[common.Deployment]) 41 | } 42 | 43 | if clusterAppDeleteMap[clusterName] != common.Rollout && clusterDeployRolloutPresent[clusterName][common.Rollout] { 44 | rolloutEp := &networking.WorkloadEntry{ 45 | Address: rolloutFqdn, 46 | Locality: ep.Locality, 47 | Ports: meshPorts[common.Rollout], 48 | Labels: map[string]string{"type": common.Rollout, "security.istio.io/tlsMode": "istio"}, 49 | } 50 | uniqueEndpointsList = append(uniqueEndpointsList, rolloutEp) 51 | requiredServices = append(requiredServices, serviceInstance[common.Rollout]) 52 | } 53 | } else { 54 | // TODO: check when will this be applicable, and then 55 | // update the required service accordingly 56 | delete(ep.Labels, "type") 57 | uniqueEndpointsList = append(uniqueEndpointsList, ep) 58 | } 59 | } 60 | 61 | serviceEntry.Endpoints = uniqueEndpointsList 62 | 63 | return requiredServices, nil 64 | } 65 | -------------------------------------------------------------------------------- /admiral/pkg/controller/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "reflect" 5 | "time" 6 | 7 | "github.com/istio-ecosystem/admiral/admiral/pkg/controller/common" 8 | log "github.com/sirupsen/logrus" 9 | ) 10 | 11 | func MapCopy(dst, src interface{}) { 12 | dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src) 13 | 14 | for _, k := range sv.MapKeys() { 15 | dv.SetMapIndex(k, sv.MapIndex(k)) 16 | } 17 | } 18 | 19 | // Subset returns whether m1 is a subset of m2 20 | func Subset(m1 map[string]string, m2 map[string]string) bool { 21 | //empty set is not a subset of any set 22 | if m1 == nil || m2 == nil || len(m1) == 0 || len(m2) < len(m1) { 23 | return false 24 | } 25 | for k, v := range m1 { 26 | if val, ok := m2[k]; ok { 27 | if !reflect.DeepEqual(val, v) { 28 | return false 29 | } 30 | } 31 | } 32 | return true 33 | } 34 | 35 | func Contains(vs []string, t string) bool { 36 | for _, v := range vs { 37 | if v == t { 38 | return true 39 | } 40 | } 41 | return false 42 | } 43 | 44 | func LogElapsedTime(op, identity, env, clusterId string) func() { 45 | start := time.Now() 46 | return func() { 47 | LogElapsedTimeSince(op, identity, env, clusterId, start) 48 | } 49 | } 50 | 51 | func LogElapsedTimeController(logger *log.Entry, logMessage string) func() { 52 | start := time.Now() 53 | return func() { 54 | logger.Infof("%s txTime=%v", 55 | logMessage, 56 | time.Since(start).Milliseconds()) 57 | } 58 | } 59 | 60 | func LogElapsedTimeForTask(logger *log.Entry, op, name, namespace, cluster, message string) func() { 61 | start := time.Now() 62 | return func() { 63 | LogElapsedTimeSinceTask(logger, op, name, namespace, cluster, message, start) 64 | } 65 | } 66 | 67 | func LogElapsedTimeSinceTask(logger *log.Entry, task, name, namespace, cluster, message string, start time.Time) { 68 | // task=%v name=%v namespace=%s cluster=%s message=%v txId=%v 69 | logger.Infof(common.CtxLogFormatWithTime, task, name, namespace, cluster, message, time.Since(start).Milliseconds()) 70 | } 71 | 72 | func LogElapsedTimeSince(op, identity, env, clusterId string, start time.Time) { 73 | log.Infof("op=%s identity=%s env=%s cluster=%s txTime=%v", op, identity, env, clusterId, time.Since(start).Milliseconds()) 74 | } 75 | -------------------------------------------------------------------------------- /admiral/pkg/core/vsrouting/routedestination.go: -------------------------------------------------------------------------------- 1 | package vsrouting 2 | 3 | import ( 4 | networkingV1Alpha3 "istio.io/api/networking/v1alpha3" 5 | ) 6 | 7 | type IRouteDestination interface { 8 | ToTLSRouteDestination() *networkingV1Alpha3.RouteDestination 9 | ToHTTPRouteDestination() *networkingV1Alpha3.HTTPRouteDestination 10 | DeepCopyInto(*RouteDestination) 11 | } 12 | 13 | type RouteDestination struct { 14 | Destination *networkingV1Alpha3.Destination 15 | Weight int32 16 | Headers *networkingV1Alpha3.Headers 17 | Type string 18 | } 19 | 20 | type RouteDestinationSorted []*RouteDestination 21 | 22 | func (r *RouteDestination) ToTLSRouteDestination() *networkingV1Alpha3.RouteDestination { 23 | return &networkingV1Alpha3.RouteDestination{ 24 | Destination: r.Destination, 25 | Weight: r.Weight, 26 | } 27 | } 28 | 29 | func (r *RouteDestination) ToHTTPRouteDestination() *networkingV1Alpha3.HTTPRouteDestination { 30 | return &networkingV1Alpha3.HTTPRouteDestination{ 31 | Destination: r.Destination, 32 | Weight: r.Weight, 33 | Headers: r.Headers, 34 | } 35 | } 36 | 37 | func (r *RouteDestination) DeepCopyInto(out *RouteDestination) { 38 | var newDestination = &networkingV1Alpha3.Destination{} 39 | if r.Destination != nil { 40 | r.Destination.DeepCopyInto(newDestination) 41 | } 42 | var newHeaders = &networkingV1Alpha3.Headers{} 43 | if r.Headers != nil { 44 | r.Headers.DeepCopyInto(newHeaders) 45 | } 46 | 47 | out.Destination = newDestination 48 | out.Weight = r.Weight 49 | out.Headers = newHeaders 50 | } 51 | 52 | func (r RouteDestinationSorted) Len() int { 53 | return len(r) 54 | } 55 | 56 | func (r RouteDestinationSorted) Less(i, j int) bool { 57 | return r[i].Destination.Host < r[j].Destination.Host 58 | } 59 | 60 | func (r RouteDestinationSorted) Swap(i, j int) { 61 | r[i], r[j] = r[j], r[i] 62 | } 63 | -------------------------------------------------------------------------------- /admiral/pkg/core/vsrouting/routedestination_test.go: -------------------------------------------------------------------------------- 1 | package vsrouting 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | networkingV1Alpha3 "istio.io/api/networking/v1alpha3" 8 | ) 9 | 10 | func TestDeepCopyInto(t *testing.T) { 11 | 12 | testCases := []struct { 13 | name string 14 | r *RouteDestination 15 | expectedHost string 16 | expectedWeight int32 17 | expectedPort uint32 18 | }{ 19 | { 20 | name: "Given a RouteDestination, " + 21 | "When destination is set to nil " + 22 | "And DeepCopyInto func is called" + 23 | "Then it should return a new RouteDestination with nil destination and different pointers", 24 | r: &RouteDestination{ 25 | Destination: nil, 26 | Weight: 10, 27 | Headers: &networkingV1Alpha3.Headers{ 28 | Request: &networkingV1Alpha3.Headers_HeaderOperations{}, 29 | }, 30 | }, 31 | expectedWeight: 10, 32 | expectedPort: 8080, 33 | }, 34 | { 35 | name: "Given a RouteDestination, " + 36 | "When header is set to nil " + 37 | "And DeepCopyInto func is called" + 38 | "Then it should return a new RouteDestination with nil headers and different pointers", 39 | r: &RouteDestination{ 40 | Destination: &networkingV1Alpha3.Destination{ 41 | Host: "host", 42 | Port: &networkingV1Alpha3.PortSelector{Number: 8080}, 43 | }, 44 | Weight: 10, 45 | Headers: nil, 46 | }, 47 | expectedWeight: 10, 48 | expectedPort: 8080, 49 | }, 50 | { 51 | name: "Given a RouteDestination, " + 52 | "When DeepCopyInto func is called" + 53 | "Then it should return a new RouteDestination with the same values and different pointers", 54 | r: &RouteDestination{ 55 | Destination: &networkingV1Alpha3.Destination{ 56 | Host: "host", 57 | Port: &networkingV1Alpha3.PortSelector{Number: 8080}, 58 | }, 59 | Weight: 10, 60 | Headers: &networkingV1Alpha3.Headers{ 61 | Request: &networkingV1Alpha3.Headers_HeaderOperations{}, 62 | }, 63 | }, 64 | expectedHost: "host", 65 | expectedWeight: 10, 66 | expectedPort: 8080, 67 | }, 68 | } 69 | 70 | for _, tc := range testCases { 71 | t.Run(tc.name, func(t *testing.T) { 72 | var newRouteDestination = &RouteDestination{} 73 | tc.r.DeepCopyInto(newRouteDestination) 74 | 75 | if tc.r.Destination != nil { 76 | if &tc.r.Destination == &newRouteDestination.Destination { 77 | require.Fail(t, "Expected new RouteDestination to have different pointers") 78 | } 79 | require.Equal(t, tc.r.Destination.Host, newRouteDestination.Destination.Host) 80 | require.Equal(t, tc.r.Destination.Port.Number, newRouteDestination.Destination.Port.Number) 81 | } 82 | if tc.r.Headers != nil { 83 | if &tc.r.Headers == &newRouteDestination.Headers { 84 | require.Fail(t, "Expected new RouteDestination to have different pointers") 85 | } 86 | } 87 | require.Equal(t, tc.r.Weight, newRouteDestination.Weight) 88 | }) 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /admiral/pkg/mocks/ConfigWriter.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.43.2. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | context "context" 7 | 8 | clusters "github.com/istio-ecosystem/admiral/admiral/pkg/clusters" 9 | 10 | logrus "github.com/sirupsen/logrus" 11 | 12 | mock "github.com/stretchr/testify/mock" 13 | 14 | v1alpha3 "istio.io/api/networking/v1alpha3" 15 | ) 16 | 17 | // ConfigWriter is an autogenerated mock type for the ConfigWriter type 18 | type ConfigWriter struct { 19 | mock.Mock 20 | } 21 | 22 | // AddServiceEntriesWithDrToAllCluster provides a mock function with given fields: ctxLogger, ctx, rr, sourceClusters, serviceEntries, isAdditionalEndpointsEnabled, isServiceEntryModifyCalledForSourceCluster, identityId, env 23 | func (_m *ConfigWriter) AddServiceEntriesWithDrToAllCluster(ctxLogger *logrus.Entry, ctx context.Context, rr *clusters.RemoteRegistry, sourceClusters map[string]string, serviceEntries map[string]*v1alpha3.ServiceEntry, isAdditionalEndpointsEnabled bool, isServiceEntryModifyCalledForSourceCluster bool, identityId string, env string) error { 24 | ret := _m.Called(ctxLogger, ctx, rr, sourceClusters, serviceEntries, isAdditionalEndpointsEnabled, isServiceEntryModifyCalledForSourceCluster, identityId, env) 25 | 26 | if len(ret) == 0 { 27 | panic("no return value specified for AddServiceEntriesWithDrToAllCluster") 28 | } 29 | 30 | var r0 error 31 | if rf, ok := ret.Get(0).(func(*logrus.Entry, context.Context, *clusters.RemoteRegistry, map[string]string, map[string]*v1alpha3.ServiceEntry, bool, bool, string, string) error); ok { 32 | r0 = rf(ctxLogger, ctx, rr, sourceClusters, serviceEntries, isAdditionalEndpointsEnabled, isServiceEntryModifyCalledForSourceCluster, identityId, env) 33 | } else { 34 | r0 = ret.Error(0) 35 | } 36 | 37 | return r0 38 | } 39 | 40 | // NewConfigWriter creates a new instance of ConfigWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. 41 | // The first argument is typically a *testing.T value. 42 | func NewConfigWriter(t interface { 43 | mock.TestingT 44 | Cleanup(func()) 45 | }) *ConfigWriter { 46 | mock := &ConfigWriter{} 47 | mock.Mock.Test(t) 48 | 49 | t.Cleanup(func() { mock.AssertExpectations(t) }) 50 | 51 | return mock 52 | } 53 | -------------------------------------------------------------------------------- /admiral/pkg/monitoring/metrics.go: -------------------------------------------------------------------------------- 1 | package monitoring 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "reflect" 7 | 8 | api "go.opentelemetry.io/otel/metric" 9 | ) 10 | 11 | // Metric interface for abstracting the different operations 12 | // for the various metric types provided by open telemetry 13 | type Metric interface { 14 | Increment(attributes api.MeasurementOption) 15 | Name() string 16 | } 17 | 18 | // NewCounter returns a new counter 19 | func NewCounter(name, description string, opts ...Options) Metric { 20 | o := createOptions(opts...) 21 | return newFloat64Counter(name, description, o) 22 | } 23 | 24 | type counter struct { 25 | name string 26 | description string 27 | ctx context.Context 28 | int64Counter api.Int64Counter 29 | } 30 | 31 | // Increment increases the value of the counter by 1, and adds the provided attributes 32 | func (c *counter) Increment(attributes api.MeasurementOption) { 33 | c.int64Counter.Add(c.ctx, 1, attributes) 34 | } 35 | 36 | // Name returns the name of the metric 37 | func (c *counter) Name() string { 38 | return c.name 39 | } 40 | 41 | func newFloat64Counter(name, description string, opts *options) *counter { 42 | ctx := context.TODO() 43 | meter := defaultMeter 44 | if reflect.ValueOf(opts.meter).IsValid() { 45 | meter = opts.meter 46 | } 47 | int64Counter, err := meter.Int64Counter( 48 | name, 49 | api.WithUnit("1"), 50 | api.WithDescription(description), 51 | ) 52 | if err != nil { 53 | log.Fatalf("error creating int64 counter: %v", err) 54 | } 55 | return &counter{ 56 | name: name, 57 | description: description, 58 | ctx: ctx, 59 | int64Counter: int64Counter, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /admiral/pkg/monitoring/monitoring.go: -------------------------------------------------------------------------------- 1 | package monitoring 2 | 3 | import ( 4 | "go.opentelemetry.io/otel/exporters/prometheus" 5 | api "go.opentelemetry.io/otel/metric" 6 | "go.opentelemetry.io/otel/sdk/metric" 7 | ) 8 | 9 | var ( 10 | meterName = "admiral_monitoring" 11 | exporter, _ = prometheus.New() 12 | provider = metric.NewMeterProvider(metric.WithReader(exporter)) 13 | defaultMeter = provider.Meter(meterName) 14 | ) 15 | 16 | func InitializeMonitoring() error { 17 | return nil 18 | } 19 | 20 | // Options accepts a pointer to options. It is used 21 | // to update the options by calling an array of functions 22 | type Options func(*options) 23 | 24 | // NewMeter creates a new meter which defines the metric scope 25 | func NewMeter(meterName string) api.Meter { 26 | return provider.Meter(meterName) 27 | } 28 | 29 | // WithMeter configures the given Meter 30 | func WithMeter(meter api.Meter) Options { 31 | return func(opts *options) { 32 | opts.meter = meter 33 | } 34 | } 35 | 36 | type options struct { 37 | meter api.Meter 38 | unit string 39 | } 40 | 41 | func createOptions(opts ...Options) *options { 42 | o := &options{} 43 | for _, opt := range opts { 44 | opt(o) 45 | } 46 | return o 47 | } 48 | -------------------------------------------------------------------------------- /admiral/pkg/registry/config.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | import ( 4 | admiralV1Alpha1 "github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1alpha1" 5 | "github.com/istio-ecosystem/admiral/admiral/pkg/controller/admiral" 6 | networking "istio.io/api/networking/v1alpha3" 7 | ) 8 | 9 | type IdentityConfig struct { 10 | IdentityName string `json:"identityName"` 11 | Clusters map[string]*IdentityConfigCluster `json:"clusters"` 12 | ClientAssets map[string]string `json:"clientAssets"` 13 | } 14 | 15 | func (config *IdentityConfig) PutClusterConfig(name string, clusterConfig IdentityConfigCluster) error { 16 | return nil 17 | } 18 | 19 | type IdentityConfigCluster struct { 20 | Name string `json:"name"` 21 | Locality string `json:"locality"` 22 | IngressEndpoint string `json:"ingressEndpoint"` 23 | IngressPort string `json:"ingressPort"` 24 | IngressPortName string `json:"ingressPortName"` 25 | // env -> rollout/deploy -> IdentityConfigEnvironment 26 | Environment map[string]*IdentityConfigEnvironment `json:"environment"` 27 | } 28 | 29 | func (config *IdentityConfigCluster) PutEnvironment(name string, environmentConfig IdentityConfigEnvironment) error { 30 | return nil 31 | } 32 | 33 | func (config *IdentityConfigCluster) PutClientAssets(clientAssets []string) error { 34 | return nil 35 | } 36 | 37 | type RegistryServiceConfig struct { 38 | Name string `json:"name"` 39 | Weight int `json:"weight,omitempty,default=-1"` 40 | Ports map[string]uint32 `json:"ports"` 41 | Selectors map[string]string `json:"selectors"` 42 | } 43 | 44 | type TrafficPolicy struct { 45 | GlobalTrafficPolicy admiralV1Alpha1.GlobalTrafficPolicy `json:"globaltrafficpolicy"` 46 | OutlierDetection admiralV1Alpha1.OutlierDetection `json:"outlierdetection"` 47 | ClientConnectionConfig admiralV1Alpha1.ClientConnectionConfig `json:"clientconnectionconfig"` 48 | } 49 | 50 | type TypeConfig struct { 51 | Strategy string `json:"strategy"` 52 | Selectors map[string]string `json:"selectors"` 53 | } 54 | 55 | type IdentityConfigEnvironment struct { 56 | Name string `json:"name"` 57 | Namespace string `json:"namespace"` 58 | Services map[string][]*RegistryServiceConfig `json:"services"` 59 | ServiceName string `json:"serviceName"` 60 | Type map[string]*TypeConfig `json:"type"` 61 | Ports []*networking.ServicePort `json:"ports"` 62 | TrafficPolicy TrafficPolicy `json:"trafficPolicy"` 63 | Event admiral.EventType `json:"event"` 64 | } 65 | 66 | type RegistryServiceConfigSorted []*RegistryServiceConfig 67 | 68 | func (r RegistryServiceConfigSorted) Len() int { 69 | return len(r) 70 | } 71 | 72 | func (r RegistryServiceConfigSorted) Less(i, j int) bool { 73 | return r[i].Name < r[j].Name 74 | } 75 | 76 | func (r RegistryServiceConfigSorted) Swap(i, j int) { 77 | r[i], r[j] = r[j], r[i] 78 | } 79 | -------------------------------------------------------------------------------- /admiral/pkg/registry/testdata/record1IdentityConfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityName": "record1", 3 | "clusters": null, 4 | "clientAssets": null 5 | } -------------------------------------------------------------------------------- /admiral/pkg/registry/testdata/record2IdentityConfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityName": "record2", 3 | "clusters": null, 4 | "clientAssets": null 5 | } -------------------------------------------------------------------------------- /admiral/pkg/test/resources/admins@fake-cluster.k8s.local: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFN3pDQ0ExZWdBd0lCQWdJUU5MbUh5bU9wUy9Ib3Y2bFdyT3hvU1RBTkJna3Foa2lHOXcwQkFRc0ZBRENCDQpqekVlTUJ3R0ExVUVDaE1WYld0alpYSjBJR1JsZG1Wc2IzQnRaVzUwSUVOQk1USXdNQVlEVlFRTERDbHpjMmhoDQpjbTFoTXpSQWFXNTBkV2wwWkdWd1lqRXlaV0VnS0ZOb2NtbHlZVzBnVTJoaGNtMWhLVEU1TURjR0ExVUVBd3d3DQpiV3RqWlhKMElITnphR0Z5YldFek5FQnBiblIxYVhSa1pYQmlNVEpsWVNBb1UyaHlhWEpoYlNCVGFHRnliV0VwDQpNQjRYRFRJeE1EZ3dNakl5TXpJek9Gb1hEVE14TURnd01qSXlNekl6T0Zvd2dZOHhIakFjQmdOVkJBb1RGVzFyDQpZMlZ5ZENCa1pYWmxiRzl3YldWdWRDQkRRVEV5TURBR0ExVUVDd3dwYzNOb1lYSnRZVE0wUUdsdWRIVnBkR1JsDQpjR0l4TW1WaElDaFRhSEpwY21GdElGTm9ZWEp0WVNreE9UQTNCZ05WQkFNTU1HMXJZMlZ5ZENCemMyaGhjbTFoDQpNelJBYVc1MGRXbDBaR1Z3WWpFeVpXRWdLRk5vY21seVlXMGdVMmhoY20xaEtUQ0NBYUl3RFFZSktvWklodmNODQpBUUVCQlFBRGdnR1BBRENDQVlvQ2dnR0JBTWM1eHBwOCtHSmxCbGVTYTc0L0VnR3J4a3VZd3M0Mmd6UzRWS2xwDQpiVTNRSXpDV2psOVd4L0hhRVVqLzA3R1dtMlhOQWVoSS91b1JIS0x0aERMWWdMelRoazBMTDFqZkZCaDV3bDRtDQplaDlCcE5EUnhXcDNQaWhScW13SGUxNFArbDR1YU1aSHNveG5WSncvQS9La05pZXhMVXZMOVZqUXpacko4Y1luDQovTjZWVjNuc1dGQjF5dVlCdHBJUHo2ODJQS291cHpqcTVRcWdOUmo1dzFHM2p0MUFabjViK004YmNKMlQvUG1hDQp4UkNVa3NxTWpwdjZhVVdpdkd1UW5yL0xaVWpxWWhSU2xLYlNoOGdjRjNmZ3VSOC9ZTjB1OVM0R1lEa2JwMXc5DQpRYitwYk5CeS9pSkdkSzJOS0JsOHRvQmdESWx2OFlmSmdEbDdCbk1uM1J2NG02T0w0VHVVVjIva25JKy9xMkZsDQpTWW8rL0F0QUVtRGV2ZEIxbUV3emRId1AvR0NsT2QrV1hjSEV2TENibC9MZ2FIeC8zZWUyNmEwb1hzVlp4N21PDQpXMGxrMU1JTXVlbTdjMTh6WXdjRDlzUXBVVG4xRTcrTGlzWHpVNC9SdVB6MHFpQUp5RzRVZ3lqY0JzdVZ6UTNqDQo2WUNaWlUxb2ZLVzQ1aWF1QmpaOUNKS2ZVUUlEQVFBQm8wVXdRekFPQmdOVkhROEJBZjhFQkFNQ0FnUXdFZ1lEDQpWUjBUQVFIL0JBZ3dCZ0VCL3dJQkFEQWRCZ05WSFE0RUZnUVVacVdGS1BrY3d4cWFOejUvbDBhZzNYMWpGNzh3DQpEUVlKS29aSWh2Y05BUUVMQlFBRGdnR0JBSlYrRE5DanViZUdqejgyQ1FFMmNSbyszektDSm42T3pTaE85WnVCDQpFM3dxUFBJT1QvOTBtZm40dEJhT0R0NmovNi9mRTZad1YyWU93UVErR3plOGZORzJEMEZYVE16a3l3Q0VwcEkyDQpIWmtIZ0JPOE45VFhja0pIR1crYkFXc0lSRHc2V2pvbThQWTN1RDA1QWEzV2RYd2ROYUE1R2hTQ3ZVVEU0bVVYDQpESjdYVjVLZjlPdEhObllXOFZ3b3B0NlBhM2tpUHdQZE9BU0E1OVUvVVFhWTRwVE5TRnBTY1A1R1VEbnVKUTUwDQpXOEdmem1FNkV4Y0ROOXRMRnVYT0oyelFpTWpKMGVKQUxIckM2UUtrRXk0anpCTFY0RFN0SURBQ2dqbzdtU28zDQphWER0NnozbTVlSUp4TmIrMG51VTRnc1BRbnQwb2sxVW9VNVpES3ZRZ3FKcGZSMU9NYUlEWkVPREJ6dXpZYTE2DQp1V0pOQ3BEaU4rZGtBMXhQQ08wVUk4STRqcDBxek9rMjNzejlEVEwvNldNbldndkZRdWxJcVRWMDNHVE1MRnEyDQpFOXpLb0JqQzdURUJrczVwSlZmMkhwVkdrUitMVzVnZnBVT0ZFanFLYnBhMEorV1hHVVRSU3R1UVBiNjQzRVBTDQpZeEl6TGR4OW04RU1zeHpYTjNQUGpDVTYxdz09DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo= 5 | server: https://localhost:6441 6 | name: apple 7 | contexts: 8 | - context: 9 | cluster: apple 10 | user: apple_admin 11 | name: apple 12 | current-context: apple 13 | kind: Config 14 | preferences: {} 15 | -------------------------------------------------------------------------------- /admiral/pkg/test/types.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "context" 5 | 6 | k8sCoreV1 "k8s.io/api/core/v1" 7 | ) 8 | 9 | type FakeConfigMapController struct { 10 | GetError error 11 | PutError error 12 | ConfigmapToReturn *k8sCoreV1.ConfigMap 13 | } 14 | 15 | func (c *FakeConfigMapController) GetConfigMap(ctx context.Context) (*k8sCoreV1.ConfigMap, error) { 16 | return c.ConfigmapToReturn, c.GetError 17 | } 18 | 19 | func (c *FakeConfigMapController) PutConfigMap(ctx context.Context, newMap *k8sCoreV1.ConfigMap) error { 20 | return c.PutError 21 | } 22 | func (c *FakeConfigMapController) GetIPPrefixForServiceEntries() (seIpPrefix string) { 23 | return "240.0" 24 | } 25 | -------------------------------------------------------------------------------- /admiral/pkg/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | coreV1 "k8s.io/api/core/v1" 5 | ) 6 | 7 | // WeightedService utility to store weighted services for argo rollouts 8 | type WeightedService struct { 9 | Weight int32 10 | Service *coreV1.Service 11 | } 12 | -------------------------------------------------------------------------------- /admiral/pkg/util/baseClient_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestNewClient_InvalidValues(t *testing.T) { 13 | 14 | client := NewClient(&Config{ 15 | AppId: "InvalidAppId", 16 | AppSecret: "InvalidSecret", 17 | Host: "host.com", 18 | }) 19 | 20 | url := fmt.Sprintf("%s/%s/apps/assetalias/%s", client.Config.Host, client.Config.BaseURI, "1234") 21 | 22 | assert.Equal(t, client.Config.ConnectionTimeoutSeconds, DefaultConnectionTimeoutSeconds) 23 | assert.Equal(t, client.Config.ReqTimeoutSeconds, DefaultReqTimeoutSeconds) 24 | assert.Equal(t, client.Config.TlsHandShakeTimeoutSeconds, DefaultTlsHandShakeTimeoutSeconds) 25 | 26 | resp, err := client.MakePrivateAuthCall(url, "tid", "GET", nil) 27 | 28 | assert.NotNil(t, err) 29 | assert.Nil(t, resp) 30 | } 31 | 32 | func Test_ReadSecret(t *testing.T) { 33 | testCases := []struct { 34 | name string 35 | secretKey string 36 | secretVal string 37 | expectedError error 38 | }{ 39 | { 40 | "Success scenario", StateSyncerSecret, "1", nil, 41 | }, 42 | { 43 | "Invalid secretKey name", "foo", "bar", errors.New("invalid input value for ReadSecret function "), 44 | }, 45 | { 46 | "Empty secret value", StateSyncerSecret, "", errors.New("error reading statesyncer secret"), 47 | }, 48 | { 49 | "Empty secret value with StateSyncerAppId", StateSyncerAppId, "", errors.New("statesyncer_appId.txt not found. Using the default appId"), 50 | }, 51 | } 52 | 53 | for _, c := range testCases { 54 | t.Run(c.name, func(t *testing.T) { 55 | _ = os.Setenv(c.secretKey, c.secretVal) 56 | secret, err := ReadSecret(c.secretKey) 57 | if c.expectedError != nil && err != nil { 58 | assert.Contains(t, err.Error(), c.expectedError.Error()) 59 | } else { 60 | if c.expectedError == nil && err != nil { 61 | t.Errorf("expected error to be: nil, got: %v", err) 62 | } 63 | } 64 | if c.expectedError == nil { 65 | assert.Equal(t, c.secretVal, secret) 66 | } 67 | }) 68 | } 69 | } 70 | func TestGetConfig(t *testing.T) { 71 | client := NewClient(&Config{ 72 | AppId: "TestAppId", 73 | AppSecret: "TestSecret", 74 | Host: "test.api.com", 75 | BaseURI: "v1", 76 | }) 77 | 78 | config := client.GetConfig() 79 | 80 | assert.Equal(t, "TestAppId", config.AppId) 81 | assert.Equal(t, "TestSecret", config.AppSecret) 82 | assert.Equal(t, "test.api.com", config.Host) 83 | assert.Equal(t, "v1", config.BaseURI) 84 | assert.Equal(t, DefaultReqTimeoutSeconds, config.ReqTimeoutSeconds) 85 | assert.Equal(t, DefaultConnectionTimeoutSeconds, config.ConnectionTimeoutSeconds) 86 | assert.Equal(t, DefaultTlsHandShakeTimeoutSeconds, config.TlsHandShakeTimeoutSeconds) 87 | } 88 | func TestCheck_NoError(t *testing.T) { 89 | assert.NotPanics(t, func() { 90 | check(nil) 91 | }) 92 | } 93 | 94 | func TestCheck_WithError(t *testing.T) { 95 | assert.Panics(t, func() { 96 | check(errors.New("test error")) 97 | }) 98 | } 99 | -------------------------------------------------------------------------------- /admiral/pkg/util/constants.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | const ( 4 | Http = "http" 5 | Grpc = "grpc" 6 | GrpcWeb = "grpc-web" 7 | Http2 = "http2" 8 | SecretShardKey = "shard" 9 | 10 | Deployment = "deployment" 11 | Rollout = "rollout" 12 | Service = "service" 13 | GlobalTrafficPolicy = "globalTrafficPolicy" 14 | OutlierDetection = "outlierDetection" 15 | ClientConnectionConfig = "clientConnectionConfig" 16 | 17 | IstioSystemNamespace = "istio-system" 18 | ) 19 | -------------------------------------------------------------------------------- /admiral/pkg/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "strings" 5 | "time" 6 | ) 7 | 8 | type AdmiralState struct { 9 | ReadOnly bool 10 | IsStateInitialized bool 11 | } 12 | 13 | var ( 14 | CurrentAdmiralState AdmiralState 15 | ) 16 | 17 | func IsAdmiralReadOnly() bool { 18 | return CurrentAdmiralState.ReadOnly 19 | } 20 | 21 | // ResyncIntervals defines the different reconciliation intervals 22 | // for kubernetes operators 23 | type ResyncIntervals struct { 24 | UniversalReconcileInterval time.Duration 25 | SeAndDrReconcileInterval time.Duration 26 | } 27 | 28 | func GetPortProtocol(name string) string { 29 | var protocol = Http 30 | if strings.Index(name, GrpcWeb) == 0 { 31 | protocol = GrpcWeb 32 | } else if strings.Index(name, Grpc) == 0 { 33 | protocol = Grpc 34 | } else if strings.Index(name, Http2) == 0 { 35 | protocol = Http2 36 | } 37 | return protocol 38 | } 39 | -------------------------------------------------------------------------------- /admiral/pkg/util/util_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "testing" 4 | 5 | func TestGetPortProtocol(t *testing.T) { 6 | cases := []struct { 7 | name string 8 | protocol string 9 | expProtocol string 10 | }{ 11 | { 12 | name: "Given valid input parameters, " + 13 | "When port name is " + Http + ", " + 14 | "Then protocol should be " + Http, 15 | protocol: Http, 16 | expProtocol: Http, 17 | }, 18 | { 19 | name: "Given valid input parameters, " + 20 | "When port name is " + GrpcWeb + ", " + 21 | "Then protocol should be " + GrpcWeb, 22 | protocol: GrpcWeb, 23 | expProtocol: GrpcWeb, 24 | }, 25 | { 26 | name: "Given valid input parameters, " + 27 | "When port name is " + Grpc + ", " + 28 | "Then protocol should be " + Grpc, 29 | protocol: Grpc, 30 | expProtocol: Grpc, 31 | }, 32 | { 33 | name: "Given valid input parameters, " + 34 | "When port name is " + Http2 + ", " + 35 | "Then protocol should be " + Http2, 36 | protocol: Http2, 37 | expProtocol: Http2, 38 | }, 39 | } 40 | for _, c := range cases { 41 | t.Run(c.name, func(t *testing.T) { 42 | protocol := GetPortProtocol(c.protocol) 43 | if protocol != c.expProtocol { 44 | t.Errorf("expected=%v, got=%v", c.expProtocol, protocol) 45 | } 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /admiral/pkg/util/variables.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | var () 4 | -------------------------------------------------------------------------------- /docs/Admiral-DynamoDB-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/Admiral-DynamoDB-view.png -------------------------------------------------------------------------------- /docs/Admiral-dynamoDB-DR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/Admiral-dynamoDB-DR.png -------------------------------------------------------------------------------- /docs/Admiral-health-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/Admiral-health-check.png -------------------------------------------------------------------------------- /docs/Admiral-state-changes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/Admiral-state-changes.png -------------------------------------------------------------------------------- /docs/Admiral_Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/Admiral_Diagram.png -------------------------------------------------------------------------------- /docs/Compatibility.md: -------------------------------------------------------------------------------- 1 | # Compatibility 2 | 3 | ## Version compatibility by Istio & K8s 4 | The below information is based on the testing done, please submit a PR if you have it working for versions outside the ones listed below. 5 | 6 | | Admiral Version | Min. Istio Version | Max. Istio Version | Min. K8s Version | Max. K8s Version 7 | |:-----------------:|:---------------------:|:---------------------:|:-----------------:|:-----------------: 8 | v0.1-beta | 1.2.3 | 1.4.6 | 1.13 | 1.14.2 9 | v0.9 | 1.2.3 | 1.5.1 | 1.13 | 1.18.0 10 | v1.0 | 1.2.3 | 1.5.6 | 1.13 | 1.18.0 11 | v1.1 | 1.5.7 | 1.7.4 | 1.13 | 1.18.0 12 | v1.2 | 1.8.6 | 1.12.1 | 1.18 | 1.22 13 | 14 | ## Admiral feature support by Istio Version 15 | 16 | | Admiral Version | Syncing | Dependency | Global Traffic Policy 17 | |:-----------------:|:---------:|:-------------:|:--------------------: 18 | v0.1-beta | Yes | Yes | No 19 | v0.9 | Yes | Yes | Yes (requires Istio 1.5.1 or higher) 20 | v1.0 | Yes | Yes | Yes (requires Istio 1.5.1 or higher) 21 | v1.1 | Yes | Yes | Yes (requires Istio 1.5.1 or higher) 22 | v1.2 | Yes | Yes | Yes (requires Istio 1.8.6 or higher) 23 | 24 | ## Tested cloud vendors 25 | 26 | | Admiral Version | Cloud vendor 27 | |:-----------------:|:---------: 28 | v0.1-beta | AWS 29 | v0.9 | AWS 30 | v1.0 | AWS, GCP, Azure 31 | v1.1 | AWS, GCP, Azure 32 | v1.2 | AWS, GCP, Azure 33 | 34 | `Note`: Please submit a PR if admiral was tested on other cloud vendors 35 | -------------------------------------------------------------------------------- /docs/DisasterRecovery.md: -------------------------------------------------------------------------------- 1 | # Disaster recovery 2 | 3 | ## Key terms 4 | 5 | ### Active Admiral/Read-Write Admiral 6 | Admiral instance which is constantly monitoring all the clusters for changes and is responsible for creating , updating and deleting the Istio custom objects 7 | like Service Entry, Destination rule, Virtual Service , Sidecar and others. 8 | 9 | ### Passive Admiral/Read-only Admiral 10 | Admiral instance which constantly monitors all the clusters for changes but does not manipulate any Istio objects. This instance does not create, update or delete Istio custom objects. 11 | 12 | ### Lock object 13 | A reference object that is used to define if an Admiral instance is active or passive. 14 | 15 | ### Lease 16 | Duration for which the usage rights are obtained on a lock object. 17 | 18 | ## What is the need for this ? 19 | 20 | As of this writing, we can only run one instance of Admiral in a Service mesh environment. We risk running into data inconsistency issues if Admiral is scaled out. 21 | Multiple Admiral instances can overwrite Service Entry and other Istio custom objects and cause non-determistic behaviour. 22 | Running only one instance of Admiral exposes us to the risk of not being able to modify Istio custom objects in case the Admiral instance is unresponsive or has network issue due to infrastructure failures. 23 | 24 | In a Service mesh spanning multiple availability zones/DR regions, we need the ability to run passive Admiral instance that can take over the responsibility of 25 | updating and creating Istio custom objects whenever the active instance encounters any issues. 26 | 27 | ## Changes to health check API - 28 | As of this writing, Admiral exposes REST APIs that can be used to check the current clusters being monitored and also data about various Istio custom objects. 29 | As we consider data from Active state Admiral as the Source of truth, we need a way to direct all REST APIs to the active state Admiral. To support this, we have enhanced the health check endpoint to 30 | include an optional query param ```checkifreadonly```. If this query param is set to true, a passive state Admiral will return a 502 whereas an active state Admiral 31 | returns a successful response. This query param can be used to configure health check diagnostic URL to decide the active instance from a pool of Admiral instances. 32 | Do not use this query param on [readiness or liveness check probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/). 33 | ![](Admiral-health-check.png) 34 | 35 | ## Creating custom DR solutions 36 | 37 | To create your own implementation of DR, please create struct which implements below interface methods. 38 | 39 | * ```runStateCheck ``` should have the logic for DR. This take AdmiralState type object as param and modifies the readonly flag to transition Admiral between Active and Passive modes 40 | * ```shouldRunOnIndependentGoRoutine ``` should return true if you want the DR logic in ```runStateCheck``` method to run on a seperate GoRoutine. 41 | 42 | ``` 43 | type AdmiralStateChecker interface { 44 | runStateCheck(ctx context.Context) 45 | shouldRunOnIndependentGoRoutine() bool 46 | } 47 | ``` 48 | * Once you have the Struct which implements above interface methods, update the ```startAdmiralStateChecker``` function to invoke your handler. 49 | * Invoke your custom implementation by setting the program argument --admiral_state_checker_name to a value used in ```startAdmiralStateChecker``` function 50 | * Please contribute your implementation to this project 51 | 52 | ## Sample implementations 53 | ### [Dynamo DB Based Admiral DR](DynamoDBBasedDR.md) 54 | 55 | 56 | -------------------------------------------------------------------------------- /docs/Index.md: -------------------------------------------------------------------------------- 1 | ## Welcome to Admiral Docs! 2 | 3 | ### [Architecture](Architecture.md) 4 | 5 | ### [Examples](Examples.md) 6 | 7 | ### [Compatibility](Compatibility.md) 8 | 9 | ### [Disaster recovery support](DisasterRecovery.md) 10 | -------------------------------------------------------------------------------- /docs/Processes.md: -------------------------------------------------------------------------------- 1 | # Processes 2 | 3 | ## Releases 4 | 5 | Admiral will be released monthly, on the second Wednesday of every month. Intuit engineers will conduct the release. 6 | 7 | ### Steps to release admiral 8 | 9 | This is applicable to anyone who makes new Admiral releases. The steps to conduct a release are outlined [here](Release-steps.md) 10 | 11 | ## Issue Management 12 | 13 | We use GitHub issues to track all of our bugs and feature requests. Each issue is assigned a milestone. This is 0.1, 0.2, ..., or 'Nebulous Future'. The milestone indicates when we think the issue should get addressed. 14 | 15 | We don't annotate issues with Releases; Milestones are used instead. We don't use GitHub projects at all, that support is disabled for our organization. 16 | 17 | ## Prioritization 18 | 19 | There will be a monthly prioritization meeting where all issues without a milestone are added, either to a future release milestone, or to `Nebulous Future`. We will take thumbs ups and commenter engagement on issues into account in making these prioritization decisions. 20 | 21 | If you would like your issue to be prioritized into an earlier release, please comment on the issue with your justification. 22 | 23 | If you would like to be included in the prioritization meeting, please reach out in the #admiral channel in [Istio Slack](https://slack.istio.io/) -------------------------------------------------------------------------------- /docs/Release-steps.md: -------------------------------------------------------------------------------- 1 | # Steps to release admiral 2 | 3 | ## Prerequisites 4 | 5 | * You are an admin on the admiral github project (to cut the release) 6 | * You have access to admiral slack channel and AdmiralProj twitter account (to make release announcements) 7 | * [Validate that the master branch build is passing](https://circleci.com/gh/istio-ecosystem/admiral/tree/master) 8 | 9 | ## Draft the release notes 10 | 11 | The release notes is maintained [here](ReleaseNotes.md). Open a PR to the release notes ahead of time and get it reviewed. 12 | 13 | ### What to cover 14 | * Any major features and examples on how to use them 15 | * Bug fixes 16 | * Any other callouts, like support for newer versions of Istio/Cloud Vendors 17 | 18 | ### How to find the issues/commits 19 | * You can find the [issues associated with a milestone](https://github.com/istio-ecosystem/admiral/issues?q=is%3Aissue+milestone%3Av1.0+) to get started. 20 | * [Commits](https://github.com/istio-ecosystem/admiral/compare/v1.0...master) between last release (the link assumes `v1.0`) and `master` branch 21 | 22 | 23 | ## Draft a new release on github.com 24 | 25 | * Go to [new release page](https://github.com/istio-ecosystem/admiral/releases/new) 26 | * Create a release with the following: 27 | Tag version = tag that matches a milestone being released (Ex: v1.1). 28 | Release title = same as Tag version 29 | Description = Ex: https://github.com/istio-ecosystem/admiral/blob/master/docs/ReleaseNotes.md#v11 (note that v11 comes from tag v1.1) 30 | 31 | ## Final checklist 32 | 33 | * Make sure the admiral release tag is published [here](https://hub.docker.com/r/admiralproj/admiral/tags) 34 | * Merge the release notes PR 35 | * Make sure the links in the release notes work 36 | * Make announcements 37 | - On istio [Admiral slack channel](https://istio.slack.com/archives/CT3F18T08) 38 | - Tweet about it [Admiral Twitter](https://twitter.com/AdmiralProj) 39 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-leap-day -------------------------------------------------------------------------------- /docs/diagrams/api-orchestration_deployment-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/diagrams/api-orchestration_deployment-flow.png -------------------------------------------------------------------------------- /docs/diagrams/api-orchestration_using_istio_and_admiral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/docs/diagrams/api-orchestration_using_istio_and_admiral.png -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Copyright The Kubernetes Authors. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | -------------------------------------------------------------------------------- /hack/update-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | SCRIPT_ROOT=$(realpath $(dirname ${BASH_SOURCE})/..) #brew install coreutils (mac) or sudo apt-get install realpath (linux) if you don't have it 8 | 9 | # Grab code-generator version from go.sum. 10 | CODEGEN_VERSION=$(grep 'k8s.io/code-generator' go.mod | awk '{print $4}' | head -1) 11 | CODEGEN_PKG=$(echo `go env GOPATH`"/pkg/mod/k8s.io/code-generator@${CODEGEN_VERSION}") 12 | 13 | echo ">> Using ${CODEGEN_PKG}" 14 | 15 | # code-generator does work with go.mod but makes assumptions about 16 | # the project living in `$GOPATH/src`. To work around this and support 17 | # any location; create a temporary directory, use this as an output 18 | # base, and copy everything back once generated. 19 | TEMP_DIR=$(mktemp -d) 20 | cleanup() { 21 | echo ">> Removing ${TEMP_DIR}" 22 | rm -rf ${TEMP_DIR} 23 | } 24 | trap "cleanup" EXIT SIGINT 25 | 26 | echo ">> Temporary output directory ${TEMP_DIR}" 27 | 28 | # Ensure we can execute. 29 | chmod +x ${CODEGEN_PKG}/generate-groups.sh ##If you get a `no file or directory` error, try `go mod download` or `go get k8s.io/code-generator@kubernetes-1.13.5` 30 | 31 | ${CODEGEN_PKG}/generate-groups.sh all \ 32 | github.com/istio-ecosystem/admiral/admiral/pkg/client github.com/istio-ecosystem/admiral/admiral/pkg/apis \ 33 | "admiral:v1alpha1" \ 34 | --output-base "${TEMP_DIR}" \ 35 | --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt 36 | 37 | # Copy everything back. 38 | cp -r "${TEMP_DIR}/github.com/istio-ecosystem/admiral/." "${SCRIPT_ROOT}/" 39 | -------------------------------------------------------------------------------- /hack/update-k8s.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -euo pipefail 3 | 4 | VERSION=${1#"v"} 5 | if [ -z "$VERSION" ]; then 6 | echo "Must specify version!" 7 | exit 1 8 | fi 9 | MODS=($( 10 | curl -sS https://raw.githubusercontent.com/kubernetes/kubernetes/v${VERSION}/go.mod | 11 | sed -n 's|.*k8s.io/\(.*\) => ./staging/src/k8s.io/.*|k8s.io/\1|p' 12 | )) 13 | for MOD in "${MODS[@]}"; do 14 | V=$( 15 | go mod download -json "${MOD}@kubernetes-${VERSION}" | 16 | sed -n 's|.*"Version": "\(.*\)".*|\1|p' 17 | ) 18 | go mod edit "-replace=${MOD}=${MOD}@${V}" 19 | done 20 | go get "k8s.io/kubernetes@v${VERSION}" 21 | -------------------------------------------------------------------------------- /hack/verify-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | SCRIPT_ROOT=$(realpath $(dirname ${BASH_SOURCE})/..) #brew install coreutils (mac) or sudo apt-get install realpath (linux) if you don't have it 8 | DIFFROOT="${SCRIPT_ROOT}/admiral/pkg" 9 | TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" 10 | _tmp="${SCRIPT_ROOT}/_tmp" 11 | 12 | cleanup() { 13 | rm -rf "${_tmp}" 14 | } 15 | trap "cleanup" EXIT SIGINT 16 | 17 | cleanup 18 | 19 | mkdir -p "${TMP_DIFFROOT}" 20 | cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" 21 | 22 | "${SCRIPT_ROOT}/hack/update-codegen.sh" 23 | echo "diffing ${DIFFROOT} against freshly generated codegen" 24 | ret=0 25 | diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? 26 | cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" 27 | if [[ $ret -eq 0 ]] 28 | then 29 | echo "${DIFFROOT} up to date." 30 | else 31 | echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh" 32 | exit 1 33 | fi -------------------------------------------------------------------------------- /install/admiral/base/deployments.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | labels: 6 | app: admiral 7 | name: admiral 8 | namespace: admiral 9 | spec: 10 | replicas: 1 11 | selector: 12 | matchLabels: 13 | app: admiral 14 | template: 15 | metadata: 16 | annotations: 17 | prometheus.io/path: "/metrics" 18 | prometheus.io/port: "6900" 19 | prometheus.io/scrape: "true" 20 | labels: 21 | app: admiral 22 | spec: 23 | serviceAccountName: admiral 24 | containers: 25 | - args: 26 | - --dependency_namespace 27 | - admiral 28 | - --secret_namespace 29 | - admiral 30 | - --sync_namespace 31 | - admiral-sync 32 | - --sync_period 33 | - 20s 34 | - --gateway_app 35 | - istio-eastwestgateway 36 | - --envoy_filter_version 37 | - "1.13" 38 | - --enable_routing_policy=true 39 | - --exportto_identity_list 40 | - "*" 41 | - --enable_sw_aware_ns_caches=true 42 | - --enable_dependency_processing=true 43 | image: docker.io/admiralproj/admiral:latest 44 | imagePullPolicy: Always 45 | livenessProbe: 46 | failureThreshold: 5 47 | httpGet: 48 | path: /health/ready 49 | port: 8080 50 | initialDelaySeconds: 15 51 | periodSeconds: 5 52 | successThreshold: 1 53 | timeoutSeconds: 1 54 | readinessProbe: 55 | httpGet: 56 | path: /health/ready 57 | port: 8080 58 | initialDelaySeconds: 10 59 | periodSeconds: 5 60 | name: admiral 61 | ports: 62 | - containerPort: 8080 63 | name: service 64 | - containerPort: 6900 65 | name: metrics 66 | resources: 67 | limits: 68 | cpu: 1 69 | memory: 2048M 70 | requests: 71 | cpu: 0.25 72 | memory: 256M 73 | 74 | --- -------------------------------------------------------------------------------- /install/admiral/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | images: 5 | - name: docker.io/admiralproj/admiral 6 | newTag: latest 7 | 8 | resources: 9 | - crds.yaml 10 | - deployments.yaml 11 | - roles.yaml 12 | - role_bindings.yaml 13 | - service_accounts.yaml 14 | - services.yaml -------------------------------------------------------------------------------- /install/admiral/base/role_bindings.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: RoleBinding 5 | metadata: 6 | name: admiral-secret-role-binding 7 | namespace: admiral 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: admiral-secret-role 12 | subjects: 13 | - kind: ServiceAccount 14 | name: admiral 15 | namespace: admiral 16 | 17 | --- 18 | 19 | apiVersion: rbac.authorization.k8s.io/v1 20 | kind: RoleBinding 21 | metadata: 22 | name: admiral-dependency-role-binding 23 | namespace: admiral 24 | roleRef: 25 | apiGroup: rbac.authorization.k8s.io 26 | kind: Role 27 | name: admiral-dependency-role 28 | subjects: 29 | - kind: ServiceAccount 30 | name: admiral 31 | namespace: admiral 32 | 33 | --- 34 | 35 | apiVersion: rbac.authorization.k8s.io/v1 36 | kind: RoleBinding 37 | metadata: 38 | name: admiral-configmap-role-binding 39 | namespace: admiral-sync 40 | roleRef: 41 | apiGroup: rbac.authorization.k8s.io 42 | kind: Role 43 | name: admiral-configmap-role 44 | subjects: 45 | - kind: ServiceAccount 46 | name: admiral 47 | namespace: admiral 48 | 49 | --- 50 | apiVersion: rbac.authorization.k8s.io/v1 51 | kind: RoleBinding 52 | metadata: 53 | name: admiral-cluster-binding 54 | namespace: istio-system 55 | roleRef: 56 | apiGroup: rbac.authorization.k8s.io 57 | kind: ClusterRole 58 | name: admiral-sync-write-envoyfilters 59 | subjects: 60 | - kind: ServiceAccount 61 | name: admiral 62 | namespace: admiral-sync 63 | 64 | --- 65 | 66 | apiVersion: rbac.authorization.k8s.io/v1 67 | kind: RoleBinding 68 | metadata: 69 | name: admiral-dependencyproxy-role-binding 70 | namespace: admiral 71 | roleRef: 72 | apiGroup: rbac.authorization.k8s.io 73 | kind: Role 74 | name: admiral-dependencyproxy-role 75 | subjects: 76 | - kind: ServiceAccount 77 | name: admiral 78 | namespace: admiral -------------------------------------------------------------------------------- /install/admiral/base/roles.yaml: -------------------------------------------------------------------------------- 1 | 2 | 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: Role 5 | metadata: 6 | name: admiral-dependency-role 7 | namespace: admiral 8 | rules: 9 | - apiGroups: ["admiral.io"] 10 | resources: ["dependencies","dependencyproxies"] 11 | verbs: ["get", "list", "watch"] 12 | 13 | --- 14 | 15 | apiVersion: rbac.authorization.k8s.io/v1 16 | kind: Role 17 | metadata: 18 | name: admiral-secret-role 19 | namespace: admiral 20 | rules: 21 | - apiGroups: [""] 22 | resources: ["secrets"] 23 | verbs: ["get", "watch", "list"] 24 | 25 | --- 26 | 27 | apiVersion: rbac.authorization.k8s.io/v1 28 | kind: Role 29 | metadata: 30 | name: admiral-configmap-role 31 | namespace: admiral-sync 32 | rules: 33 | - apiGroups: [""] 34 | resources: ["configmaps"] 35 | verbs: ["get", "update", "create"] 36 | 37 | --- 38 | 39 | kind: ClusterRole 40 | apiVersion: rbac.authorization.k8s.io/v1 41 | metadata: 42 | name: admiral-sync-write-envoyfilters 43 | namespace: admiral 44 | rules: 45 | - apiGroups: ["networking.istio.io"] 46 | resources: ['envoyfilters'] 47 | verbs: ["create", "update", "delete", "patch"] 48 | 49 | --- 50 | 51 | apiVersion: rbac.authorization.k8s.io/v1 52 | kind: Role 53 | metadata: 54 | name: admiral-dependencyproxy-role 55 | namespace: admiral 56 | rules: 57 | - apiGroups: ["admiral.io"] 58 | resources: ["dependencyproxies"] 59 | verbs: ["get", "list", "watch"] -------------------------------------------------------------------------------- /install/admiral/base/service_accounts.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: admiral 7 | namespace: admiral 8 | labels: 9 | app: admiral 10 | --- -------------------------------------------------------------------------------- /install/admiral/base/services.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: admiral-http 5 | spec: 6 | type: NodePort 7 | selector: 8 | app: admiral 9 | ports: 10 | - protocol: TCP 11 | port: 8080 12 | targetPort: 8080 13 | nodePort: 32000 14 | --- 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | name: admiral-metrics 19 | spec: 20 | type: NodePort 21 | selector: 22 | app: admiral 23 | ports: 24 | - protocol: TCP 25 | port: 6900 26 | targetPort: 6900 27 | nodePort: 32001 -------------------------------------------------------------------------------- /install/admiral/overlays/demosinglecluster/envconfig_values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: admiral 7 | namespace: admiral 8 | spec: 9 | template: 10 | 11 | spec: 12 | containers: 13 | - args: 14 | - --dependency_namespace 15 | - admiral 16 | - --secret_namespace 17 | - admiral 18 | - --sync_namespace 19 | - admiral-sync 20 | - --sync_period 21 | - 10s 22 | - --argo_rollouts=true 23 | - --envoy_filter_version 24 | - "1.13" 25 | - --enable_routing_policy=true 26 | - --exportto_identity_list 27 | - "*" 28 | - --enable_sw_aware_ns_caches=true 29 | - --enable_dependency_processing=true 30 | name: admiral 31 | -------------------------------------------------------------------------------- /install/admiral/overlays/demosinglecluster/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | images: 5 | - name: docker.io/admiralproj/admiral 6 | newTag: latest 7 | 8 | bases: 9 | - ../../base 10 | 11 | patchesStrategicMerge: 12 | - envconfig_values.yaml 13 | 14 | resources: 15 | - ns.yaml 16 | 17 | 18 | -------------------------------------------------------------------------------- /install/admiral/overlays/demosinglecluster/ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: admiral 6 | labels: 7 | istio-injection: disabled 8 | --- -------------------------------------------------------------------------------- /install/admiralremote/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | 5 | resources: 6 | - remote.yaml 7 | - crds.yaml 8 | -------------------------------------------------------------------------------- /install/sample/base/greeting.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-conf 5 | data: 6 | nginx.conf: | 7 | user nginx; 8 | worker_processes 3; 9 | error_log /var/log/nginx/error.log; 10 | events { 11 | worker_connections 10240; 12 | } 13 | http { 14 | log_format main 15 | 'remote_addr:$remote_addr\t' 16 | 'time_local:$time_local\t' 17 | 'method:$request_method\t' 18 | 'uri:$request_uri\t' 19 | 'host:$host\t' 20 | 'status:$status\t' 21 | 'bytes_sent:$body_bytes_sent\t' 22 | 'referer:$http_referer\t' 23 | 'useragent:$http_user_agent\t' 24 | 'forwardedfor:$http_x_forwarded_for\t' 25 | 'request_time:$request_time'; 26 | access_log /var/log/nginx/access.log main; 27 | server { 28 | listen 80; 29 | server_name _; 30 | location / { 31 | return 200 "Hello World! - Admiral!!"; 32 | 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /install/sample/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample 5 | 6 | resources: 7 | - namespace.yaml 8 | - greeting.yaml 9 | - webapp.yaml 10 | -------------------------------------------------------------------------------- /install/sample/base/namespace.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: sample 6 | labels: 7 | istio-injection: enabled 8 | --- 9 | -------------------------------------------------------------------------------- /install/sample/base/webapp.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: webapp 6 | --- 7 | apiVersion: apps/v1 8 | kind: Deployment 9 | metadata: 10 | name: webapp 11 | annotations: 12 | #admiral.io/ignore: "true" #Uncommenting this line will cause admiral to ignore this deployment despite the fact that it's in the mesh 13 | spec: 14 | replicas: 1 15 | selector: 16 | matchLabels: 17 | app: webapp 18 | template: 19 | metadata: 20 | annotations: 21 | admiral.io/env: stage 22 | sidecar.istio.io/inject: "true" 23 | labels: 24 | app: webapp 25 | identity: webapp 26 | #admiral-ignore: "true" #Uncommenting this line will cause admiral to ignore this deployment despite the fact that it's in the mesh 27 | spec: 28 | serviceAccountName: webapp 29 | containers: 30 | - name: webapp 31 | image: pstauffer/curl 32 | command: ["/bin/sleep", "3650d"] 33 | imagePullPolicy: IfNotPresent 34 | resources: 35 | requests: 36 | cpu: "10m" 37 | memory: "50Mi" 38 | limits: 39 | cpu: "20m" 40 | memory: "75Mi" 41 | --- 42 | apiVersion: v1 43 | kind: Service 44 | metadata: 45 | name: webapp 46 | labels: 47 | app: webapp 48 | identity: webapp 49 | spec: 50 | ports: 51 | - port: 80 52 | targetPort: 80 53 | name: http 54 | selector: 55 | app: webapp 56 | --- -------------------------------------------------------------------------------- /install/sample/depProxyExample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: DependencyProxy 3 | metadata: 4 | name: dependency-proxy-httpbin-stage 5 | namespace: admiral 6 | annotations: 7 | admiral.io/env: stage 8 | spec: 9 | destination: 10 | identity: httpbin 11 | dns_suffix: "foo" 12 | dns_prefixes: 13 | - "test0" 14 | - "test1" 15 | proxy: 16 | identity: proxy 17 | 18 | --- 19 | apiVersion: admiral.io/v1alpha1 20 | kind: DependencyProxy 21 | metadata: 22 | name: dependency-proxy-httpbin-qal 23 | namespace: admiral 24 | annotations: 25 | admiral.io/env: qal 26 | spec: 27 | destination: 28 | identity: httpbin 29 | dns_suffix: "foo" 30 | dns_prefixes: 31 | - "test2" 32 | - "test3" 33 | proxy: 34 | identity: proxy -------------------------------------------------------------------------------- /install/sample/greeting_preview.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-conf-preview 5 | namespace: sample-rollout-bluegreen 6 | data: 7 | nginx.conf: | 8 | user nginx; 9 | worker_processes 3; 10 | error_log /var/log/nginx/error.log; 11 | events { 12 | worker_connections 10240; 13 | } 14 | http { 15 | log_format main 16 | 'remote_addr:$remote_addr\t' 17 | 'time_local:$time_local\t' 18 | 'method:$request_method\t' 19 | 'uri:$request_uri\t' 20 | 'host:$host\t' 21 | 'status:$status\t' 22 | 'bytes_sent:$body_bytes_sent\t' 23 | 'referer:$http_referer\t' 24 | 'useragent:$http_user_agent\t' 25 | 'forwardedfor:$http_x_forwarded_for\t' 26 | 'request_time:$request_time'; 27 | access_log /var/log/nginx/access.log main; 28 | server { 29 | listen 80; 30 | server_name _; 31 | location / { 32 | return 200 "Hello World! - Admiral Preview!!"; 33 | 34 | } 35 | } 36 | } 37 | --- 38 | apiVersion: argoproj.io/v1alpha1 39 | kind: Rollout 40 | metadata: 41 | name: greeting 42 | namespace: sample-rollout-bluegreen 43 | labels: 44 | identity: greeting 45 | spec: 46 | replicas: 1 47 | selector: 48 | matchLabels: 49 | app: greeting 50 | template: 51 | metadata: 52 | annotations: 53 | admiral.io/env: stage 54 | sidecar.istio.io/inject: "true" 55 | labels: 56 | app: greeting 57 | identity: greeting.bluegreen 58 | spec: 59 | containers: 60 | - image: nginx 61 | name: greeting 62 | ports: 63 | - containerPort: 80 64 | volumeMounts: 65 | - mountPath: /etc/nginx 66 | name: nginx-conf 67 | readOnly: true 68 | - mountPath: /var/log/nginx 69 | name: log 70 | resources: 71 | requests: 72 | cpu: "10m" 73 | memory: "50Mi" 74 | limits: 75 | cpu: "20m" 76 | memory: "75Mi" 77 | volumes: 78 | - configMap: 79 | items: 80 | - key: nginx.conf 81 | path: nginx.conf 82 | name: nginx-conf-preview 83 | name: nginx-conf 84 | - emptyDir: {} 85 | name: log 86 | strategy: 87 | blueGreen: 88 | # activeService specifies the service to update with the new template hash at time of promotion. 89 | # This field is mandatory for the blueGreen update strategy. 90 | activeService: rollout-bluegreen-active 91 | # previewService specifies the service to update with the new template hash before promotion. 92 | # This allows the preview stack to be reachable without serving production traffic. 93 | # This field is optional. 94 | previewService: rollout-bluegreen-preview 95 | # autoPromotionEnabled disables automated promotion of the new stack by pausing the rollout 96 | # immediately before the promotion. If omitted, the default behavior is to promote the new 97 | # stack as soon as the ReplicaSet are completely ready/available. 98 | # Rollouts can be resumed using: `kubectl argo rollouts resume ROLLOUT` 99 | autoPromotionEnabled: false -------------------------------------------------------------------------------- /install/sample/greetings-ccc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: ClientConnectionConfig 3 | metadata: 4 | name: greetings-ccs 5 | namespace: greeting 6 | annotations: 7 | admiral.io/env: stage 8 | labels: 9 | identity: greeting 10 | spec: 11 | connectionPool: 12 | tcp: 13 | maxConnectionDuration: 1s 14 | http: 15 | http2MaxRequests: 100 16 | maxRequestsPerConnection: 100 17 | idleTimeout: 1s -------------------------------------------------------------------------------- /install/sample/grpc-client.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: grpc-client 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: grpc-client 11 | template: 12 | metadata: 13 | labels: 14 | app: grpc-client 15 | identity: grpc-client 16 | annotations: 17 | sidecar.istio.io/inject: "true" 18 | spec: 19 | containers: 20 | - name: grpc-client 21 | image: buoyantio/strest-grpc:latest 22 | args: 23 | - "client" 24 | - "--address=stage.grpc-server.global:80" 25 | - "--connections=2" 26 | - "--totalTargetRps=2" 27 | - "--totalRequests=10" 28 | - "--logLevel=debug" 29 | resources: 30 | requests: 31 | cpu: "10m" 32 | memory: "50Mi" 33 | limits: 34 | cpu: "20m" 35 | memory: "75Mi" 36 | -------------------------------------------------------------------------------- /install/sample/gtp-priority.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: GlobalTrafficPolicy 3 | metadata: 4 | name: gtp-service1 5 | namespace: sample 6 | annotations: 7 | admiral.io/env: stage 8 | labels: 9 | identity: greeting 10 | priority: "1" #0 value or missing label represents no priority is set, any other value determines the processing priority 11 | spec: 12 | policy: 13 | - dnsPrefix: default # default is a keyword, alternatively you can use `env` (ex: stage) 14 | lbType: 1 #0 represents TOPOLOGY, 1 represents FAILOVER 15 | target: 16 | - region: us-west-2 17 | weight: 80 18 | - region: us-east-2 19 | weight: 20 20 | -------------------------------------------------------------------------------- /install/sample/gtp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: GlobalTrafficPolicy 3 | metadata: 4 | name: gtp-service1 5 | namespace: sample 6 | annotations: 7 | admiral.io/env: stage 8 | labels: 9 | identity: greeting 10 | spec: 11 | policy: 12 | - dnsPrefix: default # default is a keyword, alternatively you can use `env` (ex: stage) 13 | lbType: 1 #0 represents TOPOLOGY, 1 represents FAILOVER 14 | target: 15 | - region: us-west-2 16 | weight: 80 17 | - region: us-east-2 18 | weight: 20 19 | -------------------------------------------------------------------------------- /install/sample/gtp_failover.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: GlobalTrafficPolicy 3 | metadata: 4 | name: gtp-service1 5 | namespace: sample 6 | annotations: 7 | admiral.io/env: stage 8 | labels: 9 | identity: greeting 10 | spec: 11 | policy: 12 | - dnsPrefix: default 13 | lbType: 0 14 | - dnsPrefix: west #a new host will be generated Ex: west..greeting.global 15 | lbType: 1 #0 represents TOPOLOGY, 1 represents FAILOVER 16 | target: 17 | - region: us-west-2 18 | weight: 100 19 | - region: us-east-2 20 | weight: 0 21 | - dnsPrefix: east 22 | lbType: 1 #0 represents TOPOLOGY, 1 represents FAILOVER 23 | target: 24 | - region: us-west-2 25 | weight: 0 26 | - region: us-east-2 27 | weight: 100 28 | -------------------------------------------------------------------------------- /install/sample/gtp_topology.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: GlobalTrafficPolicy 3 | metadata: 4 | name: gtp-service1 5 | namespace: sample 6 | annotations: 7 | admiral.io/env: stage 8 | labels: 9 | identity: greeting 10 | spec: 11 | policy: 12 | - dnsPrefix: default 13 | lbType: 0 14 | -------------------------------------------------------------------------------- /install/sample/od.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: OutlierDetection 3 | metadata: 4 | name: sample-configuration 5 | namespace: sample 6 | annotations: 7 | admiral.io/env: stage 8 | spec: 9 | selector: 10 | identity: greeting 11 | env: stage 12 | outlier_config: #TODO : How to disable it 13 | base_ejection_time: 180 14 | consecutive_gateway_errors: 10 15 | interval: 28 16 | -------------------------------------------------------------------------------- /install/sample/overlays/deployment/greeting.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: greeting 6 | namespace: sample 7 | labels: 8 | identity: greeting 9 | spec: 10 | replicas: 1 11 | selector: 12 | matchLabels: 13 | app: greeting 14 | template: 15 | metadata: 16 | annotations: 17 | admiral.io/env: stage 18 | sidecar.istio.io/inject: "true" 19 | labels: 20 | app: greeting 21 | identity: greeting 22 | spec: 23 | containers: 24 | - image: nginx 25 | name: greeting 26 | ports: 27 | - containerPort: 80 28 | volumeMounts: 29 | - mountPath: /etc/nginx 30 | name: nginx-conf 31 | readOnly: true 32 | - mountPath: /var/log/nginx 33 | name: log 34 | resources: 35 | requests: 36 | cpu: "10m" 37 | memory: "50Mi" 38 | limits: 39 | cpu: "20m" 40 | memory: "75Mi" 41 | volumes: 42 | - configMap: 43 | items: 44 | - key: nginx.conf 45 | path: nginx.conf 46 | name: nginx-conf 47 | name: nginx-conf 48 | - emptyDir: {} 49 | name: log 50 | 51 | --- 52 | apiVersion: v1 53 | kind: Service 54 | metadata: 55 | labels: 56 | app: greeting 57 | identity: greeting 58 | name: greeting 59 | spec: 60 | ports: 61 | - port: 80 62 | targetPort: 80 63 | name: http 64 | selector: 65 | app: greeting -------------------------------------------------------------------------------- /install/sample/overlays/deployment/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample 5 | 6 | bases: 7 | - ../../base 8 | 9 | resources: 10 | - greeting.yaml 11 | -------------------------------------------------------------------------------- /install/sample/overlays/grpc/grpc-server.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: grpc-server 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: grpc-server 11 | template: 12 | metadata: 13 | labels: 14 | app: grpc-server 15 | identity: grpc-server 16 | annotations: 17 | admiral.io/env: stage 18 | sidecar.istio.io/inject: "true" 19 | spec: 20 | containers: 21 | - name: grpc-server 22 | image: buoyantio/strest-grpc:latest 23 | args: 24 | - "server" 25 | - "--address=:11111" 26 | - "--logLevel=debug" 27 | ports: 28 | - name: grpc 29 | containerPort: 11111 30 | resources: 31 | requests: 32 | cpu: "10m" 33 | memory: "50Mi" 34 | limits: 35 | cpu: "20m" 36 | memory: "75Mi" 37 | --- 38 | apiVersion: v1 39 | kind: Service 40 | metadata: 41 | name: grpc-server 42 | spec: 43 | selector: 44 | app: grpc-server 45 | clusterIP: None 46 | ports: 47 | - name: grpc 48 | port: 11111 49 | targetPort: 11111 50 | -------------------------------------------------------------------------------- /install/sample/overlays/grpc/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample 5 | 6 | bases: 7 | - ../../base 8 | 9 | resources: 10 | - grpc-server.yaml 11 | -------------------------------------------------------------------------------- /install/sample/overlays/job/job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: pi 5 | labels: 6 | identity: job 7 | spec: 8 | template: 9 | metadata: 10 | annotations: 11 | sidecar.istio.io/inject: "true" 12 | labels: 13 | identity: job 14 | spec: 15 | containers: 16 | - name: pi 17 | image: perl:5.34.0 18 | command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] 19 | restartPolicy: Never 20 | backoffLimit: 4 -------------------------------------------------------------------------------- /install/sample/overlays/job/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample-job 5 | 6 | bases: 7 | - ../../base 8 | 9 | patchesStrategicMerge: 10 | - webapp.yaml 11 | 12 | resources: 13 | - job.yaml -------------------------------------------------------------------------------- /install/sample/overlays/job/webapp.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: webapp 6 | annotations: 7 | #admiral.io/ignore: "true" #Uncommenting this line will cause admiral to ignore this deployment despite the fact that it's in the mesh 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: webapp 13 | template: 14 | metadata: 15 | annotations: 16 | admiral.io/env: stage 17 | sidecar.istio.io/inject: "true" 18 | labels: 19 | app: webapp 20 | identity: jobwebapp 21 | #admiral-ignore: "true" #Uncommenting this line will cause admiral to ignore this deployment despite the fact that it's in the mesh 22 | spec: 23 | serviceAccountName: webapp 24 | containers: 25 | - name: webapp 26 | image: pstauffer/curl 27 | command: ["/bin/sleep", "3650d"] 28 | imagePullPolicy: IfNotPresent 29 | resources: 30 | requests: 31 | cpu: "10m" 32 | memory: "50Mi" 33 | limits: 34 | cpu: "20m" 35 | memory: "75Mi" -------------------------------------------------------------------------------- /install/sample/overlays/numaflow/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample-monovertex 5 | 6 | bases: 7 | - ../../base 8 | 9 | patchesStrategicMerge: 10 | - webapp.yaml 11 | 12 | resources: 13 | - monovertex.yaml -------------------------------------------------------------------------------- /install/sample/overlays/numaflow/monovertex.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: numaflow.numaproj.io/v1alpha1 2 | kind: MonoVertex 3 | metadata: 4 | name: simple-mono-vertex 5 | spec: 6 | metadata: 7 | annotations: 8 | sidecar.istio.io/inject: "true" 9 | labels: 10 | identity: monovertex 11 | source: 12 | udsource: 13 | container: 14 | image: quay.io/numaio/numaflow-java/source-simple-source:stable 15 | # transformer is an optional container to do any transformation to the incoming data before passing to the sink 16 | transformer: 17 | container: 18 | image: quay.io/numaio/numaflow-rs/source-transformer-now:stable 19 | sink: 20 | udsink: 21 | container: 22 | image: quay.io/numaio/numaflow-java/simple-sink:stable -------------------------------------------------------------------------------- /install/sample/overlays/numaflow/webapp.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: webapp 6 | annotations: 7 | #admiral.io/ignore: "true" #Uncommenting this line will cause admiral to ignore this deployment despite the fact that it's in the mesh 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: webapp 13 | template: 14 | metadata: 15 | annotations: 16 | admiral.io/env: stage 17 | sidecar.istio.io/inject: "true" 18 | labels: 19 | app: webapp 20 | identity: monovertexwebapp 21 | #admiral-ignore: "true" #Uncommenting this line will cause admiral to ignore this deployment despite the fact that it's in the mesh 22 | spec: 23 | serviceAccountName: webapp 24 | containers: 25 | - name: webapp 26 | image: pstauffer/curl 27 | command: ["/bin/sleep", "3650d"] 28 | imagePullPolicy: IfNotPresent 29 | resources: 30 | requests: 31 | cpu: "10m" 32 | memory: "50Mi" 33 | limits: 34 | cpu: "20m" 35 | memory: "75Mi" -------------------------------------------------------------------------------- /install/sample/overlays/remote/greeting-deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: greeting 6 | namespace: sample 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: greeting 12 | template: 13 | metadata: 14 | annotations: 15 | sidecar.istio.io/inject: "true" 16 | admiral.io/env: stage 17 | labels: 18 | app: greeting 19 | identity: greeting 20 | spec: 21 | containers: 22 | - image: nginx 23 | name: greeting 24 | ports: 25 | - containerPort: 80 26 | volumeMounts: 27 | - mountPath: /etc/nginx 28 | name: nginx-conf 29 | readOnly: true 30 | - mountPath: /var/log/nginx 31 | name: log 32 | resources: 33 | requests: 34 | cpu: "10m" 35 | memory: "50Mi" 36 | limits: 37 | cpu: "20m" 38 | memory: "75Mi" 39 | volumes: 40 | - configMap: 41 | items: 42 | - key: nginx.conf 43 | path: nginx.conf 44 | name: nginx-conf 45 | name: nginx-conf 46 | - emptyDir: {} 47 | name: log 48 | 49 | --- 50 | apiVersion: v1 51 | kind: Service 52 | metadata: 53 | labels: 54 | app: greeting 55 | identity: greeting 56 | name: greeting 57 | spec: 58 | ports: 59 | - port: 80 60 | targetPort: 80 61 | name: http 62 | selector: 63 | app: greeting -------------------------------------------------------------------------------- /install/sample/overlays/remote/greeting.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-conf 5 | data: 6 | nginx.conf: | 7 | user nginx; 8 | worker_processes 3; 9 | error_log /var/log/nginx/error.log; 10 | events { 11 | worker_connections 10240; 12 | } 13 | http { 14 | log_format main 15 | 'remote_addr:$remote_addr\t' 16 | 'time_local:$time_local\t' 17 | 'method:$request_method\t' 18 | 'uri:$request_uri\t' 19 | 'host:$host\t' 20 | 'status:$status\t' 21 | 'bytes_sent:$body_bytes_sent\t' 22 | 'referer:$http_referer\t' 23 | 'useragent:$http_user_agent\t' 24 | 'forwardedfor:$http_x_forwarded_for\t' 25 | 'request_time:$request_time'; 26 | access_log /var/log/nginx/access.log main; 27 | server { 28 | listen 80; 29 | server_name _; 30 | location / { 31 | return 200 "Remote cluster says: Hello World! - Admiral!!"; 32 | } 33 | } 34 | } 35 | --- -------------------------------------------------------------------------------- /install/sample/overlays/remote/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample 5 | 6 | bases: 7 | - ../../base 8 | 9 | patchesStrategicMerge: 10 | - greeting.yaml 11 | 12 | resources: 13 | - greeting-deployment.yaml 14 | 15 | -------------------------------------------------------------------------------- /install/sample/overlays/rollout-bluegreen/greeting.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Rollout 4 | metadata: 5 | name: greeting 6 | labels: 7 | identity: greeting 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: greeting 13 | template: 14 | metadata: 15 | annotations: 16 | admiral.io/env: stage 17 | sidecar.istio.io/inject: "true" 18 | labels: 19 | app: greeting 20 | identity: greeting.bluegreen 21 | spec: 22 | containers: 23 | - image: nginx 24 | name: greeting 25 | ports: 26 | - containerPort: 80 27 | volumeMounts: 28 | - mountPath: /etc/nginx 29 | name: nginx-conf 30 | readOnly: true 31 | - mountPath: /var/log/nginx 32 | name: log 33 | resources: 34 | requests: 35 | cpu: "10m" 36 | memory: "50Mi" 37 | limits: 38 | cpu: "20m" 39 | memory: "75Mi" 40 | volumes: 41 | - configMap: 42 | items: 43 | - key: nginx.conf 44 | path: nginx.conf 45 | name: nginx-conf 46 | name: nginx-conf 47 | - emptyDir: {} 48 | name: log 49 | strategy: 50 | blueGreen: 51 | # activeService specifies the service to update with the new template hash at time of promotion. 52 | # This field is mandatory for the blueGreen update strategy. 53 | activeService: rollout-bluegreen-active 54 | # previewService specifies the service to update with the new template hash before promotion. 55 | # This allows the preview stack to be reachable without serving production traffic. 56 | # This field is optional. 57 | previewService: rollout-bluegreen-preview 58 | # autoPromotionEnabled disables automated promotion of the new stack by pausing the rollout 59 | # immediately before the promotion. If omitted, the default behavior is to promote the new 60 | # stack as soon as the ReplicaSet are completely ready/available. 61 | # Rollouts can be resumed using: `kubectl argo rollouts resume ROLLOUT` 62 | autoPromotionEnabled: false 63 | --- 64 | kind: Service 65 | apiVersion: v1 66 | metadata: 67 | name: rollout-bluegreen-active 68 | labels: 69 | app: greeting 70 | identity: greeting.bluegreen 71 | namespace: sample 72 | spec: 73 | ports: 74 | - name: http 75 | port: 80 76 | targetPort: 80 77 | selector: 78 | app: greeting 79 | 80 | --- 81 | kind: Service 82 | apiVersion: v1 83 | metadata: 84 | name: rollout-bluegreen-preview 85 | labels: 86 | app: greeting 87 | identity: greeting.bluegreen 88 | namespace: sample 89 | spec: 90 | ports: 91 | - name: http 92 | port: 80 93 | targetPort: 80 94 | selector: 95 | app: greeting -------------------------------------------------------------------------------- /install/sample/overlays/rollout-bluegreen/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample-rollout-bluegreen 5 | 6 | bases: 7 | - ../../base 8 | 9 | resources: 10 | - greeting.yaml -------------------------------------------------------------------------------- /install/sample/overlays/rollout-canary/greeting.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Rollout 3 | metadata: 4 | name: greeting-canary 5 | labels: 6 | identity: greeting.canary 7 | spec: 8 | replicas: 2 9 | selector: 10 | matchLabels: 11 | app: greeting 12 | template: 13 | metadata: 14 | annotations: 15 | admiral.io/env: stage 16 | sidecar.istio.io/inject: "true" 17 | labels: 18 | app: greeting 19 | identity: greeting.canary 20 | spec: 21 | containers: 22 | - image: nginx 23 | name: greeting 24 | ports: 25 | - containerPort: 80 26 | volumeMounts: 27 | - mountPath: /etc/nginx 28 | name: nginx-conf 29 | readOnly: true 30 | - mountPath: /var/log/nginx 31 | name: log 32 | resources: 33 | requests: 34 | cpu: "10m" 35 | memory: "50Mi" 36 | limits: 37 | cpu: "20m" 38 | memory: "75Mi" 39 | volumes: 40 | - configMap: 41 | items: 42 | - key: nginx.conf 43 | path: nginx.conf 44 | name: nginx-conf 45 | name: nginx-conf 46 | - emptyDir: {} 47 | name: log 48 | strategy: 49 | canary: # A new field that used to provide configurable options for a Canary strategy 50 | canaryService: rollout-canary-svc # required 51 | stableService: rollout-stable-svc # required 52 | trafficRouting: 53 | istio: 54 | virtualService: 55 | name: rollout-vsvc # required 56 | routes: 57 | - primary 58 | steps: 59 | - setWeight: 10 60 | - pause: 61 | duration: 300 #300 seconds 62 | --- 63 | kind: Service 64 | apiVersion: v1 65 | metadata: 66 | name: rollout-stable-svc 67 | labels: 68 | app: greeting 69 | identity: greeting.canary 70 | namespace: sample 71 | spec: 72 | ports: 73 | - name: http 74 | port: 80 75 | targetPort: 80 76 | selector: 77 | app: greeting 78 | --- 79 | kind: Service 80 | apiVersion: v1 81 | metadata: 82 | name: rollout-canary-svc 83 | labels: 84 | app: greeting 85 | identity: greeting.canary 86 | namespace: sample 87 | spec: 88 | ports: 89 | - name: http 90 | port: 80 91 | targetPort: 80 92 | selector: 93 | app: greeting 94 | 95 | --- 96 | apiVersion: networking.istio.io/v1alpha3 97 | kind: VirtualService 98 | metadata: 99 | name: rollout-vsvc 100 | spec: 101 | gateways: 102 | - mesh 103 | hosts: 104 | - istio-rollout.dev.argoproj.io 105 | http: 106 | - name: primary # referenced in canary.trafficRouting.istio.virtualService.routes 107 | route: 108 | - destination: 109 | host: rollout-stable-svc # referenced in canary.stableService 110 | weight: 100 111 | - destination: 112 | host: rollout-canary-svc # referenced in canary.canaryService 113 | weight: 0 -------------------------------------------------------------------------------- /install/sample/overlays/rollout-canary/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiversion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: sample-rollout-canary 5 | 6 | bases: 7 | - ../../base 8 | 9 | resources: 10 | - greeting.yaml 11 | -------------------------------------------------------------------------------- /install/sample/rp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: RoutingPolicy 3 | metadata: 4 | name: greeting-routing-policy 5 | annotations: 6 | admiral.io/env: stage 7 | labels: 8 | identity: greeting 9 | spec: 10 | plugin: greeting 11 | hosts: 12 | - qal.greeting.mesh 13 | config: 14 | cachePrefix: "prefix-v1-a" 15 | cacheTtlSec: "1440" 16 | dispatcherUrl: "http://test.does.not.matter.mesh/" 17 | env: "qal" 18 | algorithmName: "ShardedRouting" 19 | wasmPath: "/etc/istio/extensions/dynamicrouter.wasm" 20 | pathPrefix: "/wpcatalog,/consumercatalog,/v1/company/{id}/auth/hydrate,/consumercatalog" 21 | 22 | -------------------------------------------------------------------------------- /install/sample/sample_dep.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admiral.io/v1alpha1 3 | kind: Dependency 4 | metadata: 5 | name: dependency-webapp 6 | namespace: admiral 7 | spec: 8 | source: webapp 9 | #TODO this value is hard coded to identity 10 | identityLabel: identity 11 | destinations: 12 | - greeting 13 | --- 14 | 15 | --- 16 | apiVersion: admiral.io/v1alpha1 17 | kind: Dependency 18 | metadata: 19 | name: dependency-grpc-client 20 | namespace: admiral 21 | spec: 22 | source: grpc-client 23 | identityLabel: identity 24 | destinations: 25 | - grpc-server 26 | --- 27 | 28 | --- 29 | apiVersion: admiral.io/v1alpha1 30 | kind: Dependency 31 | metadata: 32 | name: dependency-greeting 33 | namespace: admiral 34 | spec: 35 | source: greeting 36 | #TODO this value is hard coded to identity 37 | identityLabel: identity 38 | destinations: 39 | - httpbin 40 | --- 41 | apiVersion: admiral.io/v1alpha1 42 | kind: Dependency 43 | metadata: 44 | name: dependency-job 45 | namespace: admiral 46 | spec: 47 | source: job 48 | identityLabel: identity 49 | destinations: 50 | - greeting 51 | 52 | --- 53 | apiVersion: admiral.io/v1alpha1 54 | kind: Dependency 55 | metadata: 56 | name: dependency-monovertex 57 | namespace: admiral 58 | spec: 59 | source: monovertex 60 | identityLabel: identity 61 | destinations: 62 | - greeting -------------------------------------------------------------------------------- /install/sample/trafficconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: admiral.io/v1alpha1 2 | kind: TrafficConfig 3 | metadata: 4 | annotations: 5 | dnsName: slowstarttest-e2e.api.intuit.com 6 | labels: 7 | asset: Intuit.services.mesh.slowstarttest 8 | env: e2e 9 | name: intuit.services.mesh.slowstarttest-e2e 10 | namespace: admiral 11 | spec: 12 | edgeService: 13 | slowStartConfig: 14 | - workloadEnvSelectors: 15 | - e2e 16 | duration: 60s 17 | filters: 18 | - name: filter-3387192 19 | - name: filter--671448791 20 | routes: 21 | - config: 22 | - targetGroupSelector: Default 23 | targetSelector: e2e--186971779 24 | filterSelector: filter--671448791 25 | inbound: /* 26 | name: all 27 | outbound: /* 28 | timeout: 5000 29 | workloadEnvSelectors: 30 | - e2e 31 | - config: 32 | - targetGroupSelector: Default 33 | targetSelector: e2e--186971779 34 | filterSelector: filter-3387192 35 | inbound: /health/full 36 | name: Health Check 37 | outbound: /health/full 38 | timeout: 5000 39 | workloadEnvSelectors: 40 | - e2e 41 | targetGroups: 42 | - name: Default - Single Swimlane 43 | weights: 44 | - name: Default - All Traffic 45 | weight: 100 46 | - name: DefaultGroup 47 | weights: 48 | - name: Default 49 | weight: 100 50 | targets: 51 | - name: e2e--186971779 52 | port: 80 53 | socketTimeout: 5000 54 | quotaGroup: 55 | totalQuotaGroups: 56 | - description: Total capacity of service 57 | name: Total Throttling Plan 58 | podLevelThreshold: 100 59 | quotas: 60 | - algorithm: scalable 61 | behaviour: softThrottle 62 | keyType: any 63 | maxAmount: 200 64 | name: Total 65 | rule: /* 66 | timePeriod: 1s 67 | regionLevelLimit: true 68 | workloadEnvSelectors: 69 | - e2e 70 | workloadEnvs: 71 | - e2e -------------------------------------------------------------------------------- /install/scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true; do 4 | clustername=$(kubectl config current-context) 5 | 6 | if [[ $clustername == *"ppd"* || $clustername == *"prd"* || $clustername == *"prod"* ]] 7 | then 8 | echo "\$clustername is not a dev cluster" 9 | exit 1 10 | fi 11 | printf "k8s cluster: %s\n" "$clustername" 12 | printf "Namespaces ['admiral','admiral-sync','sample', 'sample-rollout-canary', 'sample-rollout-bluegreen'] will be deleted.\nDo you wish to proceed?\n" 13 | options="Please enter yes/Y/y or no/N/n" 14 | echo $options 15 | read -p "" yn 16 | case $yn in 17 | [Yy]* ) kubectl delete namespace admiral; kubectl delete namespace admiral-sync; kubectl delete namespace sample; kubectl delete namespace sample-rollout-canary; kubectl delete namespace sample-rollout-bluegreen; break;; 18 | [Nn]* ) exit;; 19 | * ) echo $options;; 20 | esac 21 | done 22 | -------------------------------------------------------------------------------- /install/scripts/cluster-secret.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -gt "0" ]; then 4 | local_cluster=$1 5 | fi 6 | 7 | if [ "$#" -gt "1" ]; then 8 | remote_cluster=$2 9 | fi 10 | 11 | if [ "$#" -gt "2" ]; then 12 | namespace_secrets=$3 13 | fi 14 | 15 | 16 | 17 | #TBD make sure you have context switched 18 | export KUBECONFIG=$remote_cluster 19 | if [ -z "$KUBECONFIG" ] 20 | then 21 | echo "\$KUBECONFIG is not set" 22 | exit 1 23 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 24 | then 25 | echo "\$KUBECONFIG is not for a dev cluster" 26 | exit 1 27 | fi 28 | 29 | #prep for creating kubeconfig of remote cluster 30 | export WORK_DIR=$(pwd) 31 | CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}" | sed -e 's/[^A-Za-z0-9.-]/-/g') 32 | export KUBECFG_FILE=/tmp/${CLUSTER_NAME} 33 | SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}") 34 | NAMESPACE_SYNC=admiral-sync 35 | SERVICE_ACCOUNT=admiral 36 | SECRET_NAME=admiral-token 37 | CA_DATA=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE_SYNC} -o "jsonpath={.data['ca\.crt']}") 38 | RAW_TOKEN=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE_SYNC} -o "jsonpath={.data['token']}") 39 | TOKEN=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE_SYNC} -o "jsonpath={.data['token']}" | base64 --decode) 40 | 41 | #echo 'TOKEN' 42 | #echo $TOKEN 43 | 44 | #create kubeconfig for remote cluster 45 | cat < ${KUBECFG_FILE} 46 | apiVersion: v1 47 | clusters: 48 | - cluster: 49 | certificate-authority-data: ${CA_DATA} 50 | server: ${SERVER} 51 | name: ${CLUSTER_NAME} 52 | contexts: 53 | - context: 54 | cluster: ${CLUSTER_NAME} 55 | user: ${CLUSTER_NAME} 56 | name: ${CLUSTER_NAME} 57 | current-context: ${CLUSTER_NAME} 58 | kind: Config 59 | preferences: {} 60 | users: 61 | - name: ${CLUSTER_NAME} 62 | user: 63 | token: ${TOKEN} 64 | EOF 65 | 66 | #export variables for initializing the remote cluster creds on control plane cluster 67 | cat < remote_cluster_env_vars 68 | export CLUSTER_NAME=${CLUSTER_NAME} 69 | export KUBECFG_FILE=${KUBECFG_FILE} 70 | EOF 71 | 72 | source remote_cluster_env_vars 73 | 74 | #TBD make sure you have context switched 75 | #create secret on control plane cluster to connect to remote cluster 76 | 77 | #export KUBECONFIG=~/.kube/config 78 | #kubectx minikube 79 | export KUBECONFIG=$local_cluster 80 | if [ -z "$KUBECONFIG" ] 81 | then 82 | echo "\$KUBECONFIG is not set" 83 | exit 1 84 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 85 | then 86 | echo "\$KUBECONFIG is not for a dev cluster" 87 | exit 1 88 | fi 89 | 90 | kubectl delete secret ${CLUSTER_NAME} -n $namespace_secrets 91 | kubectl create secret generic ${CLUSTER_NAME} --from-file ${KUBECFG_FILE} -n $namespace_secrets 92 | kubectl label secret ${CLUSTER_NAME} admiral/sync=true -n $namespace_secrets 93 | 94 | rm -rf remote_cluster_env_vars 95 | rm -rf $KUBECFG_FILE 96 | -------------------------------------------------------------------------------- /install/scripts/dev_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash +x 2 | 3 | if [ -z "$ADMIRAL_HOME" ] 4 | then 5 | echo "\$ADMIRAL_HOME is not set" 6 | exit 1 7 | fi 8 | 9 | if [ -z "$KUBECONFIG" ] 10 | then 11 | echo "\$KUBECONFIG is not set" 12 | exit 1 13 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 14 | then 15 | echo "\$KUBECONFIG is not for a dev cluster" 16 | exit 1 17 | fi 18 | 19 | cd $ADMIRAL_HOME 20 | 21 | make gen-yaml 22 | 23 | kubectl apply -f $ADMIRAL_HOME/out/yaml/remotecluster.yaml 24 | 25 | kubectl apply -f $ADMIRAL_HOME/out/yaml/demosinglecluster.yaml 26 | 27 | kubectl delete deployment admiral -n admiral 28 | 29 | $ADMIRAL_HOME/install/scripts/cluster-secret.sh $KUBECONFIG $KUBECONFIG admiral 30 | 31 | kubectl apply -f $ADMIRAL_HOME/out/yaml/sample.yaml 32 | 33 | kubectl apply -f $ADMIRAL_HOME/out/yaml/sample_dep.yaml 34 | -------------------------------------------------------------------------------- /install/scripts/install_admiral.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -eq 0 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | install_dir=$1 6 | 7 | #verify KUBECONFIG is set 8 | if [ -z "$KUBECONFIG" ] 9 | then 10 | echo "\$KUBECONFIG is not set" 11 | exit 1 12 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 13 | then 14 | echo "\$KUBECONFIG is not for a dev cluster" 15 | exit 1 16 | fi 17 | 18 | #Install admiral 19 | 20 | kubectl delete svc -n admiral admiral-http 21 | kubectl delete svc -n admiral admiral-metrics 22 | kubectl apply -f $install_dir/yaml/remotecluster.yaml 23 | kubectl apply -f $install_dir/yaml/demosinglecluster.yaml 24 | 25 | #Verify admiral is running 26 | kubectl rollout status deployment admiral -n admiral 27 | -------------------------------------------------------------------------------- /install/scripts/install_numaflow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$KUBECONFIG" ] 4 | then 5 | echo "\$KUBECONFIG is not set" 6 | exit 1 7 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 8 | then 9 | echo "\$KUBECONFIG is not for the dev cluster" 10 | exit 1 11 | fi 12 | 13 | echo "**********Installing numaflow *********" 14 | kubectl create ns numaflow-system 15 | kubectl apply -n numaflow-system -f https://raw.githubusercontent.com/numaproj/numaflow/stable/config/install.yaml 16 | kubectl apply -f https://raw.githubusercontent.com/numaproj/numaflow/stable/examples/0-isbsvc-jetstream.yaml 17 | echo "****Numaflow installed*******" 18 | -------------------------------------------------------------------------------- /install/scripts/install_prometheus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -eq 0 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | install_dir=$1 6 | 7 | #verify KUBECONFIG is set 8 | if [ -z "$KUBECONFIG" ] 9 | then 10 | echo "\$KUBECONFIG is not set" 11 | exit 1 12 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 13 | then 14 | echo "\$KUBECONFIG is not for a dev cluster" 15 | exit 1 16 | fi 17 | 18 | kubectl delete svc prometheus -n istio-system 19 | kubectl apply -f $install_dir/yaml/prometheus.yaml 20 | -------------------------------------------------------------------------------- /install/scripts/install_rollouts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$KUBECONFIG" ] 4 | then 5 | echo "\$KUBECONFIG is not set" 6 | exit 1 7 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 8 | then 9 | echo "\$KUBECONFIG is not for the dev cluster" 10 | exit 1 11 | fi 12 | 13 | echo "**********Installing rollouts *********" 14 | kubectl create namespace argo-rollouts 15 | kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml 16 | kubectl rollout status deployment argo-rollouts -n argo-rollouts 17 | echo "****Rollouts installed*******" 18 | -------------------------------------------------------------------------------- /install/scripts/install_sample_services.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -eq 0 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | install_dir=$1 6 | 7 | #verify KUBECONFIG is set 8 | if [ -z "$KUBECONFIG" ] 9 | then 10 | echo "\$KUBECONFIG is not set" 11 | exit 1 12 | elif [[ $KUBECONFIG == *"ppd"* || $KUBECONFIG == *"prd"* || $KUBECONFIG == *"prod"* ]] 13 | then 14 | echo "\$KUBECONFIG is not for a dev cluster" 15 | exit 1 16 | fi 17 | 18 | #Install the dependency CR 19 | 20 | kubectl apply -f $install_dir/yaml/sample_dep.yaml 21 | 22 | #Install test services 23 | 24 | kubectl apply -f $install_dir/yaml/sample.yaml 25 | kubectl apply -f $install_dir/yaml/proxy.yaml 26 | kubectl apply -f $install_dir/yaml/gtp_failover.yaml 27 | kubectl apply -f $install_dir/yaml/sample-greeting-rollout-bluegreen.yaml 28 | kubectl apply -f $install_dir/yaml/sample-greeting-rollout-canary.yaml 29 | kubectl apply -f $install_dir/yaml/grpc.yaml 30 | kubectl apply -f $install_dir/yaml/job_sample.yaml 31 | kubectl apply -f $install_dir/yaml/numaflow_sample.yaml 32 | 33 | #Install the dependencyProxy resource 34 | kubectl apply -f $install_dir/yaml/depProxyExample.yaml 35 | 36 | #wait for the deployments to come up 37 | kubectl rollout status deployment greeting -n sample 38 | kubectl rollout status deployment webapp -n sample 39 | kubectl rollout status deployment proxy-deploy-stage -n proxy 40 | kubectl rollout status deployment proxy-deploy-qal -n proxy 41 | 42 | 43 | kubectl rollout status deployment webapp -n sample-rollout-bluegreen 44 | 45 | checkRolloutStatus() { 46 | rolloutName=$1 47 | namespace=$2 48 | status=$(kubectl get rollout -n $2 $1 -o jsonpath="{.status.readyReplicas}") 49 | 50 | if [[ "$status" == "1" ]]; then 51 | return 0 52 | else 53 | echo "Waiting rollout $1 in $2 namespace is not in Running phase $status" 54 | return 1 55 | fi 56 | } 57 | 58 | export -f checkRolloutStatus 59 | 60 | timeout 180s bash -c "until checkRolloutStatus greeting sample-rollout-bluegreen ; do sleep 10; done" 61 | if [[ $? -eq 124 ]] 62 | then 63 | exit 1 64 | fi 65 | # Update BlueGreen Rollout with new preview release 66 | kubectl apply -f $install_dir/yaml/greeting_preview.yaml 67 | 68 | #Verify that admiral created service names for 'greeting' service 69 | checkse() { 70 | identity=$1 71 | num_ses=$(kubectl get serviceentry -n admiral-sync | grep $1 -c) 72 | 73 | if [ -z "$num_ses" ] || [ $num_ses -lt 1 ] 74 | then 75 | echo "No service entries created for $identity workload" 76 | return 1; 77 | else 78 | echo "Admiral did it's magic for $identity workload" 79 | return 0 80 | fi 81 | } 82 | export -f checkse 83 | for identity in webapp greeting greeting.canary greeting.bluegreen grpc-server stage.proxy.global-se qal.proxy.global-se; do 84 | timeout 180s bash -c "until checkse $identity; do sleep 10; done" 85 | if [[ $? -eq 124 ]] 86 | then 87 | exit 1 88 | fi 89 | done 90 | -------------------------------------------------------------------------------- /logo/admiral_logo_final-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/admiral_logo_final-01.jpg -------------------------------------------------------------------------------- /logo/admiral_logo_final-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/admiral_logo_final-02.jpg -------------------------------------------------------------------------------- /logo/admiral_logo_final.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/admiral_logo_final.ai -------------------------------------------------------------------------------- /logo/img/admiral_logo_final_admiral_on_dark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/img/admiral_logo_final_admiral_on_dark.jpg -------------------------------------------------------------------------------- /logo/img/admiral_logo_final_admiral_on_dark_text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/img/admiral_logo_final_admiral_on_dark_text.jpg -------------------------------------------------------------------------------- /logo/img/admiral_logo_final_admiral_on_white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/img/admiral_logo_final_admiral_on_white.jpg -------------------------------------------------------------------------------- /logo/img/admiral_logo_final_admiral_on_white_text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/img/admiral_logo_final_admiral_on_white_text.jpg -------------------------------------------------------------------------------- /logo/png/admiral_logo_final-darkbackground_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/png/admiral_logo_final-darkbackground_text.png -------------------------------------------------------------------------------- /logo/png/admiral_logo_final-whitebg_no_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/png/admiral_logo_final-whitebg_no_text.png -------------------------------------------------------------------------------- /logo/png/admiral_logo_final_admiral_on_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/png/admiral_logo_final_admiral_on_dark.png -------------------------------------------------------------------------------- /logo/png/admiral_logo_final_admiral_on_white_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/istio-ecosystem/admiral/7b3c4e43d495d2b409d0390011ce4b5e5d5daecb/logo/png/admiral_logo_final_admiral_on_white_text.png -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Integration tests 2 | 3 | Note that these scripts do not including the kubectl version compatibility with k8s server version. 4 | You have to install the appropriate kubectl version before running these tests. 5 | 6 | ## Run 7 | ```bash 8 | ./run.sh "1.14.2" "1.4.3" "../out" 9 | ``` -------------------------------------------------------------------------------- /tests/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 1 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | rm -rf "istio-$istio_version"* 6 | minikube delete -------------------------------------------------------------------------------- /tests/client_discovery_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | ## This test verifies if the Client Discovery (Mesh egress works as expected) works 4 | ## Validates the mesh endpoints for greeting are exported to job and numaflow types as mesh clients 5 | 6 | #Test 7 | output=$(kubectl get se stage.greeting.global-se -n admiral-sync -o yaml | grep sample-job) 8 | 9 | if [[ "$output" == *"sample-job"* ]]; then 10 | echo "PASS" 11 | else 12 | echo "FAIL" 13 | echo $output 14 | exit 1 15 | fi 16 | 17 | output=$(kubectl get se stage.greeting.global-se -n admiral-sync -o yaml | grep sample-monovertex) 18 | 19 | if [[ "$output" == *"sample-monovertex"* ]]; then 20 | echo "PASS" 21 | else 22 | echo "FAIL" 23 | echo $output 24 | exit 1 25 | fi 26 | 27 | exit 0 28 | -------------------------------------------------------------------------------- /tests/create_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 1 ] && { echo "Usage: $0 "; exit 1; } 4 | 5 | k8s_version=$1 6 | driver="--vm-driver=virtualbox" 7 | 8 | # apple silicon does not support virtualbox 9 | if [[ "$OSTYPE" == "darwin"* && $(uname -m) == 'arm64' ]]; then 10 | driver="--driver=docker" 11 | fi 12 | 13 | echo "Creating K8s cluster with version: $k8s_version" 14 | 15 | if [[ $IS_LOCAL == "false" ]]; then 16 | sudo apt-get update 17 | sudo apt-get install -y conntrack 18 | sudo sysctl fs.protected_regular=0 19 | sudo -E minikube start --vm-driver=none --kubernetes-version=$k8s_version 20 | else 21 | echo "Creating K8s cluster with virtualbox vm driver" 22 | minikube start --memory=4096 --cpus=4 --kubernetes-version=$k8s_version $driver 23 | #label node for locality load balancing 24 | kubectl label nodes minikube --overwrite failure-domain.beta.kubernetes.io/region=us-west-2 25 | fi 26 | -------------------------------------------------------------------------------- /tests/install_istio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function ver { printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' ' '); } 4 | 5 | [ $# -lt 2 ] && { echo "Usage: $0 [osx|osx-arm64|linux]" ; exit 1; } 6 | 7 | istio_version=$1 8 | os=$2 9 | 10 | 11 | echo "Installing Istio version: $istio_version" 12 | 13 | #Download & extract Istio 14 | 15 | #Downloading istiofunction ver { printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' ' '); } 16 | 17 | wget "https://github.com/istio/istio/releases/download/$istio_version/istio-$istio_version-$os.tar.gz" 18 | 19 | #Extracting istio 20 | tar -xf "istio-$istio_version-$os.tar.gz" 21 | 22 | #Create istio-system namespace 23 | 24 | kubectl create ns istio-system 25 | 26 | #Create k8s secret to be used by Citadel for mTLS cert generation 27 | kubectl create secret generic cacerts -n istio-system --from-file="istio-$istio_version/samples/certs/ca-cert.pem" --from-file="istio-$istio_version/samples/certs/ca-key.pem" --from-file="istio-$istio_version/samples/certs/root-cert.pem" --from-file="istio-$istio_version/samples/certs/cert-chain.pem" 28 | 29 | #Generate, install and verify Istio CRDs 30 | 31 | cat < cluster1.yaml 32 | apiVersion: install.istio.io/v1alpha1 33 | kind: IstioOperator 34 | spec: 35 | meshConfig: 36 | defaultConfig: 37 | proxyMetadata: 38 | # Enable Istio agent to handle DNS requests for known hosts 39 | # Unknown hosts will automatically be resolved using upstream dns servers in resolv.conf 40 | ISTIO_META_DNS_CAPTURE: "true" 41 | values: 42 | pilot: 43 | resources: 44 | requests: 45 | cpu: 20m 46 | memory: 128Mi 47 | global: 48 | meshID: admiral1 49 | multiCluster: 50 | clusterName: admiral1 51 | network: admiral1 52 | proxy: 53 | resources: 54 | requests: 55 | cpu: 20m 56 | memory: 64Mi 57 | limits: 58 | cpu: 80m 59 | memory: 256Mi 60 | components: 61 | ingressGateways: 62 | - name: istio-eastwestgateway 63 | label: 64 | istio: eastwestgateway 65 | app: istio-eastwestgateway 66 | enabled: true 67 | k8s: 68 | env: 69 | # sni-dnat adds the clusters required for AUTO_PASSTHROUGH mode 70 | - name: ISTIO_META_ROUTER_MODE 71 | value: "sni-dnat" 72 | service: 73 | ports: 74 | - name: status-port 75 | port: 15021 76 | targetPort: 15021 77 | - name: tls 78 | port: 15443 79 | targetPort: 15443 80 | EOF 81 | 82 | if [ $(ver $istio_version) -lt $(ver 1.8.6) ] 83 | then 84 | echo "Istio version $istio_version is no longer officially supported by this version of Admiral" 85 | exit 1 86 | #install istio core with DNS proxying enabled and multicluster enabled 87 | else 88 | "./istio-$istio_version/bin/istioctl" install -f cluster1.yaml -y 89 | fi 90 | rm -rf cluster1.yaml 91 | kubectl rollout status deployment istiod -n istio-system 92 | 93 | -------------------------------------------------------------------------------- /tests/master_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | (cd ../; make gen-yaml) 4 | 5 | k8s_versions=( 6 | # "1.18.0" 7 | "1.16.8" 8 | # "1.14.2" 9 | ) 10 | istio_versions=( 11 | # "1.4.6" 12 | "1.5.1" 13 | ) 14 | 15 | 16 | for k8s_version in "${k8s_versions[@]}" 17 | do 18 | for istio_version in "${istio_versions[@]}" 19 | do 20 | echo "Testing with k8s verision: $k8s_version and istio version: $istio_version" 21 | ./run.sh $k8s_version $istio_version "../out" 22 | # pass=$(./run.sh $k8s_version $istio_version "../out" | grep -c "PASS") 23 | # if [ $pass -lt 1 ] 24 | # then 25 | # echo "FAIL: k8s verision: $k8s_version and istio version: $istio_version" 26 | # else 27 | # echo "PASS: k8s verision: $k8s_version and istio version: $istio_version" 28 | # fi 29 | done 30 | done 31 | -------------------------------------------------------------------------------- /tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | 5 | [ $# -lt 3 ] && { echo "Usage: $0 " ; exit 1; } 6 | 7 | k8s_version=$1 8 | istio_version=$2 9 | install_dir=$3 10 | os="" 11 | source ./create_cluster.sh $k8s_version 12 | # Uncomment below line if setup fails due to KUBECONFIG not set 13 | export KUBECONFIG=~/.kube/config 14 | # change $os from "linux" to "osx" when running on local computer 15 | if [[ "$OSTYPE" == "darwin"* && $(uname -m) == 'arm64' ]]; then 16 | os="osx-arm64" 17 | elif [[ "$OSTYPE" == "darwin"* ]]; then 18 | os="osx" 19 | else 20 | os="linux-amd64" 21 | fi 22 | ./install_istio.sh $istio_version $os 23 | 24 | $install_dir/scripts/install_admiral.sh $install_dir 25 | $install_dir/scripts/install_rollouts.sh 26 | $install_dir/scripts/install_numaflow.sh 27 | $install_dir/scripts/cluster-secret.sh $KUBECONFIG $KUBECONFIG admiral 28 | $install_dir/scripts/install_sample_services.sh $install_dir 29 | 30 | #allow for stabilization of DNS and Istio SEs before running tests 31 | sleep 10 32 | ./test1.sh "webapp" "sample" "greeting" 33 | ./test2.sh "webapp" "sample-rollout-bluegreen" "greeting.bluegreen" 34 | ./test5.sh "webapp" "sample-rollout-bluegreen" "greeting.bluegreen" 35 | ./test2.sh "webapp" "sample-rollout-canary" "greeting.canary" 36 | 37 | #cleanup to fee up the pipeline minkube resources 38 | if [[ $IS_LOCAL == "false" ]]; then 39 | kubectl scale --replicas=0 deploy webapp -n sample 40 | kubectl scale --replicas=0 deploy greeting -n sample 41 | kubectl scale --replicas=0 deploy webapp -n sample-rollout-bluegreen 42 | kubectl scale --replicas=0 rollout greeting -n sample-rollout-bluegreen 43 | fi 44 | ./test3.sh "grpc-client" "sample" "grpc-server" $install_dir 45 | 46 | ./test4.sh "webapp" "sample" 47 | # Testing routing policy 48 | ./test6.sh "sample" "1.13" $install_dir 49 | 50 | ./client_discovery_test.sh 51 | 52 | ./cleanup.sh $istio_version -------------------------------------------------------------------------------- /tests/test1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 3 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | source=$1 6 | source_ns=$2 7 | dest=$3 8 | 9 | #Test 10 | output=$(kubectl exec --namespace=sample -it $(kubectl get pod -l "app=$source" --namespace=$source_ns -o jsonpath='{.items[0].metadata.name}') -c $source -- curl -v "http://stage.$dest.global" && echo "") 11 | 12 | if [[ "$output" == *"Admiral"* ]]; then 13 | echo "PASS" 14 | exit 0 15 | else 16 | echo "FAIL" 17 | echo $output 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /tests/test2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 3 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | source=$1 6 | source_ns=$2 7 | dest=$3 8 | 9 | #Test 10 | output=$(kubectl exec --namespace=$source_ns -it $(kubectl get pod -l "app=$source" --namespace=$source_ns -o jsonpath='{.items[0].metadata.name}') -c $source -- curl -v "http://stage.$dest.global" && echo "") 11 | 12 | if [[ "$output" == *"Admiral"* ]]; then 13 | echo "PASS" 14 | exit 0 15 | else 16 | echo "FAIL" . $output 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /tests/test3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 3 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | deploy_and_test() { 6 | source=$1 7 | source_ns=$2 8 | dest=$3 9 | install_dir=$4 10 | 11 | #Deploy the grpc client pod to run requests against the grpc endpoint 12 | kubectl apply -f $install_dir/yaml/grpc-client.yaml -n $source_ns 13 | 14 | kubectl rollout status deploy grpc-client -n $source_ns 15 | 16 | sleep 15 17 | 18 | #Test, expecting to expect the grpc client to complete the requests with 100% success 19 | output=($(kubectl logs --namespace=$source_ns $(kubectl get pod -l "app=$source" --namespace=$source_ns -o jsonpath='{.items[0].metadata.name}') -c $source | egrep -o '"good": ([0-9]+)')) 20 | 21 | if [[ "${output[1]}" -gt 0 ]]; then 22 | echo "PASS" 23 | return 0 24 | else 25 | echo "FAIL" . $output 26 | kubectl get serviceentry -n admiral-sync 27 | kubectl get pods -n $source_ns 28 | kubectl logs --namespace=$source_ns $(kubectl get pod -l "app=$source" --namespace=$source_ns -o jsonpath='{.items[0].metadata.name}') -c $source 29 | return 1 30 | fi 31 | kubectl delete deploy grpc-client -n $source_ns 32 | } 33 | 34 | export -f deploy_and_test 35 | timeout 90s bash -c "until deploy_and_test $1 $2 $3 $4; do sleep 2; done" 36 | if [[ $? -eq 124 ]] 37 | then 38 | exit 1 39 | fi 40 | 41 | 42 | -------------------------------------------------------------------------------- /tests/test4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 2 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | test() { 6 | #Delete the deployment 7 | 8 | #Test, expecting to expect the grpc client to complete the requests with 100% success 9 | output=($(kubectl get se --namespace=admiral-sync | grep "stage.$source.global" | wc -l)) 10 | if [[ "${output}" -gt 0 ]]; then 11 | echo "FAIL" 12 | kubectl get se --namespace=admiral-sync 13 | return 1 14 | else 15 | echo "PASS" 16 | return 0 17 | fi 18 | 19 | } 20 | source=$1 21 | source_ns=$2 22 | kubectl delete deploy $source -n $source_ns 23 | 24 | export -f test 25 | timeout 120s bash -c "until test; do sleep 10; done" 26 | if [[ $? -eq 124 ]] 27 | then 28 | exit 1 29 | fi 30 | -------------------------------------------------------------------------------- /tests/test5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 3 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | source=$1 6 | source_ns=$2 7 | dest=$3 8 | 9 | #Test 10 | output=$(kubectl exec --namespace=$source_ns -it $(kubectl get pod -l "app=$source" --namespace=$source_ns -o jsonpath='{.items[0].metadata.name}') -c $source -- curl -v "http://preview.stage.$dest.global" && echo "") 11 | 12 | if [[ "$output" == *"Admiral Preview"* ]]; then 13 | echo "Rollout BlueGreen Preview: PASS" 14 | exit 0 15 | else 16 | echo "FAIL" . $output 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /tests/test6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ $# -lt 3 ] && { echo "Usage: $0 " ; exit 1; } 4 | 5 | deploy_and_test() { 6 | source_ns=$1 7 | envoy_version=$2 8 | install_dir=$3 9 | 10 | #Install the routing policy 11 | 12 | kubectl apply -f $install_dir/yaml/rp.yaml -n $source_ns 13 | 14 | 15 | sleep 15 16 | 17 | #Test, expecting envoy filter with correct version to be present in istio-system namespace 18 | output=($(kubectl get envoyfilters.networking.istio.io -n istio-system | grep dynamicrouting| grep $envoy_version)) 19 | 20 | 21 | if [[ "$output" != "" ]]; then 22 | echo "PASS" 23 | return 0 24 | else 25 | echo "FAIL" . $output 26 | kubectl get envoyfilters -n istio-system 27 | kubectl get pod --all-namespaces 28 | kubectl get dependencies --all-namespaces 29 | return 1 30 | fi 31 | kubectl delete -f $install_dir/yaml/rp.yaml -n $source_ns 32 | } 33 | 34 | export -f deploy_and_test 35 | timeout 90s bash -c "until deploy_and_test $1 $2 $3; do sleep 2; done" 36 | if [[ $? -eq 124 ]] 37 | then 38 | exit 1 39 | fi 40 | 41 | 42 | --------------------------------------------------------------------------------