├── CODEOWNERS ├── img └── readme │ ├── slack-128.png │ ├── slack-dark-128.png │ ├── community.svg │ ├── meshery-logo.svg │ ├── meshery-logo-light-text-side.svg │ └── meshery-logo-dark-text-side.svg ├── nsx-sm ├── config_templates │ ├── namespace.yml │ ├── circuit_breaking.tmpl │ ├── book_info_product_page_circuit_breaking.tmpl │ ├── smi │ │ ├── split_v1alpha1_trafficsplit_crd.yaml │ │ ├── operator.yaml │ │ └── rbac.yaml │ └── httpbin.yaml ├── install-smi-nsx-sm_test.go ├── install-smi-nsx-sm.go ├── yaml.go ├── client.go ├── vet.go ├── supported_ops.go ├── install-nsx-sm.go └── nsx-sm.go ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE │ ├── question.md │ ├── ci.yml │ ├── documentation.md │ ├── feature_request.md │ └── bug_report.md ├── workflows │ ├── release-drafter.yml │ ├── slack.yml │ └── ci.yml ├── PULL_REQUEST_TEMPLATE.md ├── release-drafter.yml ├── stale.yml ├── config.yml └── welcome │ ├── Meshery-celebration-Dark.svg │ └── Meshery-celebration-Light.svg ├── CONTRIBUTING.md ├── .gitignore ├── Makefile ├── Dockerfile ├── main.go ├── go.mod ├── README.md ├── LICENSE ├── go.sum └── meshes └── meshops.pb.go /CODEOWNERS: -------------------------------------------------------------------------------- 1 | @girishranganathan 2 | @leecalcote 3 | -------------------------------------------------------------------------------- /img/readme/slack-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meshery-extensions/meshery-tanzu-sm/HEAD/img/readme/slack-128.png -------------------------------------------------------------------------------- /nsx-sm/config_templates/namespace.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: {{.namespace}} 6 | -------------------------------------------------------------------------------- /img/readme/slack-dark-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meshery-extensions/meshery-tanzu-sm/HEAD/img/readme/slack-dark-128.png -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Meshery 2 | You want to contribute to the project? Yay! We want you to! Visit our centralized instructions for [contributing](https://github.com/meshery/meshery/blob/master/CONTRIBUTING.md#contributing). 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | 15 | .vscode 16 | 17 | meshery-istio -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General question 3 | about: Request information about the project; clarify behavior of the software 4 | title: '' 5 | labels: 'question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **How can we help?** 11 | A brief description of what question(s) you have and how we can help clarify. 12 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | # our release branch 6 | branches: 7 | - master 8 | 9 | jobs: 10 | update_release_draft: 11 | runs-on: ubuntu-latest 12 | steps: 13 | # Drafts your next Release notes as Pull Requests are merged into "master" 14 | - uses: release-drafter/release-drafter@v5 15 | with: 16 | config-name: release-drafter.yml 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /nsx-sm/config_templates/circuit_breaking.tmpl: -------------------------------------------------------------------------------- 1 | apiVersion: networking.nsx-sm.io/v1alpha3 2 | kind: DestinationRule 3 | metadata: 4 | name: httpbin 5 | spec: 6 | host: httpbin 7 | trafficPolicy: 8 | tls: 9 | mode: NSX-SM_MUTUAL 10 | connectionPool: 11 | tcp: 12 | maxConnections: 1 13 | http: 14 | http1MaxPendingRequests: 1 15 | maxRequestsPerConnection: 1 16 | outlierDetection: 17 | consecutiveErrors: 1 18 | interval: 1s 19 | baseEjectionTime: 3m 20 | maxEjectionPercent: 100 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | protoc-setup: 2 | cd meshes 3 | wget https://raw.githubusercontent.com/layer5io/meshery/master/meshes/meshops.proto 4 | 5 | proto: 6 | protoc -I meshes/ meshes/meshops.proto --go_out=plugins=grpc:./meshes/ 7 | 8 | docker: 9 | DOCKER_BUILDKIT=1 docker build -t meshery/meshery-tanzu-sm . 10 | 11 | docker-run: 12 | (docker rm -f meshery-tanzu-sm) || true 13 | docker run --name meshery-tanzu-sm -d \ 14 | -p 10000:10000 \ 15 | -e DEBUG=true \ 16 | meshery/meshery-tanzu-sm 17 | 18 | run: 19 | DEBUG=true GOPROXY=direct GOSUMDB=off go run main.go -------------------------------------------------------------------------------- /nsx-sm/config_templates/book_info_product_page_circuit_breaking.tmpl: -------------------------------------------------------------------------------- 1 | apiVersion: networking.nsx-sm.io/v1alpha3 2 | kind: DestinationRule 3 | metadata: 4 | name: productpage 5 | spec: 6 | host: productpage 7 | subsets: 8 | - labels: 9 | version: v1 10 | name: v1 11 | trafficPolicy: 12 | tls: 13 | mode: NSX-SM_MUTUAL 14 | connectionPool: 15 | tcp: 16 | maxConnections: 1 17 | http: 18 | http1MaxPendingRequests: 1 19 | maxRequestsPerConnection: 1 20 | outlierDetection: 21 | consecutiveErrors: 1 22 | interval: 1s 23 | baseEjectionTime: 3m 24 | maxEjectionPercent: 100 -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Description** 2 | 3 | This PR fixes # 4 | 5 | **Notes for Reviewers** 6 | 7 | 8 | **[Signed commits](../CONTRIBUTING.md#signing-off-on-commits-developer-certificate-of-origin)** 9 | - [ ] Yes, I signed my commits. 10 | 11 | 12 | 24 | -------------------------------------------------------------------------------- /nsx-sm/config_templates/smi/split_v1alpha1_trafficsplit_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: trafficsplits.split.smi-spec.io 5 | spec: 6 | additionalPrinterColumns: 7 | - JSONPath: .spec.service 8 | description: The service 9 | name: Service 10 | type: string 11 | group: split.smi-spec.io 12 | names: 13 | kind: TrafficSplit 14 | listKind: TrafficSplitList 15 | plural: trafficsplits 16 | singular: trafficsplit 17 | scope: Namespaced 18 | subresources: 19 | status: {} 20 | version: v1alpha1 21 | versions: 22 | - name: v1alpha1 23 | served: true 24 | storage: true 25 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$NEXT_PATCH_VERSION' 2 | tag-template: 'v$NEXT_PATCH_VERSION' 3 | categories: 4 | - title: '🚀 Features' 5 | labels: 6 | - 'kind/feature' 7 | - 'kind/enhancement' 8 | - title: '🐛 Bug Fixes' 9 | labels: 10 | - 'kind/fix' 11 | - 'kind/bugfix' 12 | - 'kind/bug' 13 | - title: '🧰 Maintenance' 14 | labels: 15 | - 'kind/chore' 16 | - 'area/ci' 17 | - 'area/tests' 18 | - title: 📖 Documentation 19 | label: area/docs 20 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 21 | template: | 22 | ## What's New 23 | $CHANGES 24 | 25 | ## Contributors 26 | 27 | Thank you to our contributors for making this release possible: 28 | $CONTRIBUTORS -------------------------------------------------------------------------------- /nsx-sm/install-smi-nsx-sm_test.go: -------------------------------------------------------------------------------- 1 | package nsx-sm 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func Test_getSMIYamls(t *testing.T) { 10 | logrus.SetLevel(logrus.DebugLevel) 11 | tests := []struct { 12 | name string 13 | want string 14 | wantErr bool 15 | }{ 16 | { 17 | name: "valid case", 18 | wantErr: false, 19 | }, 20 | } 21 | for _, tt := range tests { 22 | t.Run(tt.name, func(t *testing.T) { 23 | _, err := getSMIYamls() 24 | if (err != nil) != tt.wantErr { 25 | t.Errorf("getSMIYamls() error = %v, wantErr %v", err, tt.wantErr) 26 | return 27 | } 28 | // if got != tt.want { 29 | // t.Errorf("getSMIYamls() = %v, want %v", got, tt.want) 30 | // } 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🛠 Continuous Integration / DevOps 3 | about: Improve or update workflows or other automation 4 | title: '[CI]' 5 | labels: 'area/ci' 6 | assignees: '' 7 | --- 8 | #### Current Behavior 9 | 10 | 11 | #### Desired Behavior 12 | 13 | 14 | #### Implementation 15 | 16 | 17 | #### Acceptance Tests 18 | 19 | 20 | #### Reference: 21 | 22 | - [Meshery Build & Release Strategy](https://docs.meshery.io/project/build-and-release) 23 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13.1 as bd 2 | RUN adduser --disabled-login --gecos "" appuser 3 | WORKDIR /github.com/layer5io/meshery-nsx-sm 4 | ADD . . 5 | RUN GOPROXY=direct GOSUMDB=off go build -ldflags="-w -s" -a -o /meshery-nsx-sm . 6 | RUN find . -name "*.go" -type f -delete; mv nsx-sm / 7 | RUN wget -O /nsx-sm.tar.gz https://github.com/nsx-sm/nsx-sm/releases/download/1.3.0/nsx-sm-1.3.0-linux.tar.gz 8 | 9 | FROM alpine 10 | RUN apk --update add ca-certificates 11 | RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2 12 | COPY --from=bd /meshery-nsx-sm /app/ 13 | COPY --from=bd /nsx-sm /app/nsx-sm 14 | COPY --from=bd /nsx-sm.tar.gz /app/ 15 | COPY --from=bd /etc/passwd /etc/passwd 16 | ENV nsx-sm_VERSION=nsx-sm-1.3.0 17 | USER appuser 18 | WORKDIR /app 19 | CMD ./meshery-nsx-sm 20 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 45 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 10 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - issue/willfix 8 | # Label to use when marking an issue as stale 9 | staleLabel: issue/stale 10 | # Comment to post when marking an issue as stale. Set to `false` to disable 11 | markComment: > 12 | This issue has been automatically marked as stale because it has not had 13 | recent activity. It will be closed if no further activity occurs. Thank you 14 | for your contributions. 15 | # Comment to post when closing a stale issue. Set to `false` to disable 16 | closeComment: > 17 | This issue is being automatically closed due to inactivity. 18 | However, you may choose to reopen this issue. 19 | -------------------------------------------------------------------------------- /nsx-sm/install-smi-nsx-sm.go: -------------------------------------------------------------------------------- 1 | package nsx-sm 2 | 3 | import ( 4 | "io/ioutil" 5 | "path" 6 | "strings" 7 | 8 | "github.com/pkg/errors" 9 | "github.com/sirupsen/logrus" 10 | ) 11 | 12 | const smiBasePath = "nsx-sm/config_templates/smi/" 13 | 14 | var smiFiles = []string{ 15 | "split_v1alpha1_trafficsplit_crd.yaml", 16 | "rbac.yaml", 17 | "operator.yaml", 18 | } 19 | 20 | func getSMIYamls() (string, error) { 21 | var result strings.Builder 22 | for _, smiFile := range smiFiles { 23 | fileContents, err := ioutil.ReadFile(path.Join(smiBasePath, smiFile)) 24 | if err != nil { 25 | err = errors.Wrap(err, "unable to read file") 26 | logrus.Error(err) 27 | return "", err 28 | } 29 | result.Write(fileContents) 30 | result.WriteString("\n---\n") 31 | } 32 | logrus.Debugf("generated yaml: %s", result.String()) 33 | return result.String(), nil 34 | } 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 📄 Documentation issue 3 | about: Issues related to documentation. 4 | title: '[Docs]' 5 | labels: 'area/docs, framework/jekyll, language/markdown' 6 | assignees: '' 7 | --- 8 | #### Current State 9 | 10 | 11 | #### Desired State 12 | 13 | 14 | --- 15 | 16 | #### [Contributor Guides](https://docs.meshery.io/project/contributing) and Resources 17 | - 📚 [Instructions for contributing to documentation](https://docs.meshery.io/project/contributing/contributing-docs) 18 | - Meshery documentation [site](https://docs.meshery.io/) and [source](https://github.com/meshery/meshery/tree/master/docs) 19 | - 🛠 [Meshery Build & Release Strategy](https://docs.meshery.io/project/build-and-release) 20 | - 🎨 Wireframes and designs for Meshery UI in [Figma](https://www.figma.com/file/SMP3zxOjZztdOLtgN4dS2W/Meshery-UI) 21 | - 🙋🏾🙋🏼 Questions: [Discussion Forum](https://meshery.io/community#discussion-forums) and [Community Slack](http://slack.meshery.io) 22 | -------------------------------------------------------------------------------- /nsx-sm/config_templates/smi/operator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: smi-adapter-nsx-sm 5 | namespace: nsx-sm-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | name: smi-adapter-nsx-sm 11 | template: 12 | metadata: 13 | labels: 14 | name: smi-adapter-nsx-sm 15 | annotations: 16 | sidecar.nsx-sm.io/inject: "false" 17 | spec: 18 | serviceAccountName: smi-adapter-nsx-sm 19 | containers: 20 | - name: smi-adapter-nsx-sm 21 | image: layer5/smi-nsx-sm:latest 22 | command: 23 | - smi-adapter-nsx-sm 24 | imagePullPolicy: Always 25 | env: 26 | - name: WATCH_NAMESPACE 27 | value: "" 28 | - name: POD_NAME 29 | valueFrom: 30 | fieldRef: 31 | fieldPath: metadata.name 32 | - name: OPERATOR_NAME 33 | value: "smi-adapter-nsx-sm" 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an enhancement to this project 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | --- 8 | **Current Behavior** 9 | A brief description of what the problem is. (e.g. I need to be able to...) 10 | 11 | **Desired Behavior** 12 | A brief description of the enhancement. 13 | 14 | --- 15 | [Optional] **Alternatives** 16 | A brief description of any alternative solutions or features you've considered. 17 | 18 | [Optional] **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | 21 | ### Contributor Resources 22 | 23 | The meshery.io website uses Jekyll and GitHub Pages. Site content is found under the [`master` branch](https://github.com/meshery/meshery.io/tree/master). 24 | - See the [Contributing to Meshery.io Website](https://github.com/meshery/meshery.io#contributing-to-the-mesheryio-website) section of the readme.md and other [contributing instructions](https://docs.meshery.io/project/contributing), too. 25 | - See Meshery site designs in this [Figma designfile](https://www.figma.com/file/SMP3zxOjZztdOLtgN4dS2W/Meshery-UI?node-id=110%3A1). Fill-in the [Meshery Community Member Form](https://meshery.io/newcomers) and join the [Meshery Community Slack](http://slack.meshery.io) for access. 26 | -------------------------------------------------------------------------------- /nsx-sm/config_templates/httpbin.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: httpbin 5 | labels: 6 | app: httpbin 7 | spec: 8 | ports: 9 | - name: http 10 | port: 8000 11 | targetPort: 80 12 | selector: 13 | app: httpbin 14 | --- 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | name: httpbin 19 | spec: 20 | replicas: 1 21 | template: 22 | metadata: 23 | labels: 24 | app: httpbin 25 | version: v1 26 | spec: 27 | containers: 28 | - image: docker.io/kennethreitz/httpbin 29 | imagePullPolicy: IfNotPresent 30 | name: httpbin 31 | ports: 32 | - containerPort: 80 33 | --- 34 | apiVersion: networking.nsx-sm.io/v1alpha3 35 | kind: Gateway 36 | metadata: 37 | name: httpbin-gateway 38 | spec: 39 | selector: 40 | nsx-sm: ingressgateway 41 | servers: 42 | - port: 43 | number: 80 44 | name: http 45 | protocol: HTTP 46 | hosts: 47 | - "*" 48 | --- 49 | apiVersion: networking.nsx-sm.io/v1alpha3 50 | kind: VirtualService 51 | metadata: 52 | name: httpbin 53 | spec: 54 | hosts: 55 | - "*" 56 | gateways: 57 | - httpbin-gateway 58 | http: 59 | - match: 60 | route: 61 | - destination: 62 | host: httpbin 63 | port: 64 | number: 8000 65 | --- -------------------------------------------------------------------------------- /img/readme/community.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug/issue report 3 | about: Report an issue to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | --- 8 | **Description** 9 | A brief description of the issue. 10 | 11 | **Expected Behavior** 12 | A brief description of what you expected to happen. 13 | 14 | **Screenshots** 15 | Add screenshots, if applicable, to help explain your problem. 16 | 17 | **Enviroment:** 18 | - OS: [e.g. Ubuntu] 19 | - Browser: [e.g. Chrome, Safari] 20 | - Version: [e.g. 22] 21 | - Device: [e.g. laptop, iPhone 8] 22 | 23 | --- 24 | [Optional] **To Reproduce** 25 | Steps to reproduce the behavior: 26 | 1. Go to '...' 27 | 2. Click on '....' 28 | 3. Scroll down to '....' 29 | 4. See error 30 | 31 | [Optional] **Additional Context** 32 | Add any other context about the problem here. 33 | 34 | ### Contributor Resources 35 | 36 | The meshery.io website uses Jekyll and GitHub Pages. Site content is found under the [`master` branch](https://github.com/meshery/meshery.io/tree/master). 37 | - See the [Contributing to Meshery.io Website](https://github.com/meshery/meshery.io#contributing-to-the-mesheryio-website) section of the readme.md and other [contributing instructions](https://docs.meshery.io/project/contributing), too. 38 | - See Meshery site designs in this [Figma designfile](https://www.figma.com/file/SMP3zxOjZztdOLtgN4dS2W/Meshery-UI?node-id=110%3A1). Fill-in the [Meshery Community Member Form](https://meshery.io/newcomers) and join the [Meshery Community Slack](http://slack.meshery.io) for access. 39 | -------------------------------------------------------------------------------- /.github/workflows/slack.yml: -------------------------------------------------------------------------------- 1 | name: Slack Notify 2 | 3 | on: 4 | watch: 5 | types: [started] 6 | issues: 7 | types: [labeled] 8 | 9 | jobs: 10 | star-notify: 11 | if: github.event_name == 'watch' 12 | name: Notify Slack on star 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Get current star count 16 | run: | 17 | echo "STARS=$(curl --silent 'https://api.github.com/repos/${{ github.repository }}' -H 'Accept: application/vnd.github.preview' | jq '.stargazers_count')" >> $GITHUB_ENV 18 | - name: Notify Slack 19 | env: 20 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} 21 | uses: pullreminders/slack-action@master 22 | with: 23 | args: '{\"channel\":\"CSK7N9TGX\",\"text\":\"${{ github.actor }} just starred ${{ github.repository }}! (https://github.com/${{ github.repository }}/stargazers) Total ⭐️: ${{ env.STARS }}\"}' 24 | 25 | good-first-issue-notify: 26 | if: github.event_name == 'issues' && (github.event.label.name == 'good first issue' || github.event.label.name == 'first-timers-only') 27 | name: Notify Slack for new good-first-issue 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Notify Slack 31 | env: 32 | SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} 33 | uses: pullreminders/slack-action@master 34 | with: 35 | args: '{\"channel\":\"C019426UBNY\",\"type\":\"section\",\"text\":\":new: Good first issue up for grabs: ${{ github.event.issue.title }} - ${{ github.event.issue.html_url }} \"}' 36 | 37 | -------------------------------------------------------------------------------- /nsx-sm/config_templates/smi/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: smi-adapter-nsx-sm 5 | namespace: nsx-sm-system 6 | --- 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | kind: ClusterRole 9 | metadata: 10 | name: smi-adapter-nsx-sm 11 | namespace: nsx-sm-system 12 | rules: 13 | - apiGroups: 14 | - "" 15 | resources: 16 | - pods 17 | - services 18 | - endpoints 19 | - persistentvolumeclaims 20 | - events 21 | - configmaps 22 | - secrets 23 | verbs: 24 | - '*' 25 | - apiGroups: 26 | - apps 27 | resources: 28 | - deployments 29 | - daemonsets 30 | - replicasets 31 | - statefulsets 32 | verbs: 33 | - '*' 34 | - apiGroups: 35 | - monitoring.coreos.com 36 | resources: 37 | - servicemonitors 38 | verbs: 39 | - get 40 | - create 41 | - apiGroups: 42 | - apps 43 | resourceNames: 44 | - smi-adapter-nsx-sm 45 | resources: 46 | - deployments/finalizers 47 | verbs: 48 | - update 49 | - apiGroups: 50 | - split.smi-spec.io 51 | resources: 52 | - '*' 53 | verbs: 54 | - '*' 55 | - apiGroups: 56 | - networking.nsx-sm.io 57 | resources: 58 | - '*' 59 | verbs: 60 | - '*' 61 | --- 62 | kind: ClusterRoleBinding 63 | apiVersion: rbac.authorization.k8s.io/v1 64 | metadata: 65 | name: smi-adapter-nsx-sm 66 | subjects: 67 | - kind: ServiceAccount 68 | name: smi-adapter-nsx-sm 69 | namespace: nsx-sm-system 70 | roleRef: 71 | kind: ClusterRole 72 | name: smi-adapter-nsx-sm 73 | apiGroup: rbac.authorization.k8s.io -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright Meshery Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "flag" 19 | "fmt" 20 | "net" 21 | "os" 22 | 23 | "google.golang.org/grpc" 24 | "google.golang.org/grpc/grpclog" 25 | 26 | "github.com/sirupsen/logrus" 27 | 28 | mesh "github.com/layer5io/meshery-nsx-sm/meshes" 29 | ) 30 | 31 | var ( 32 | gRPCPort = flag.Int("grpc-port", 10011, "The gRPC server port") 33 | ) 34 | 35 | var log grpclog.LoggerV2 36 | 37 | func init() { 38 | log = grpclog.NewLoggerV2(os.Stdout, os.Stdout, os.Stdout) 39 | grpclog.SetLoggerV2(log) 40 | } 41 | 42 | func main() { 43 | flag.Parse() 44 | 45 | if os.Getenv("DEBUG") == "true" { 46 | logrus.SetLevel(logrus.DebugLevel) 47 | } 48 | 49 | addr := fmt.Sprintf(":%d", *gRPCPort) 50 | lis, err := net.Listen("tcp", addr) 51 | if err != nil { 52 | logrus.Fatalln("Failed to listen:", err) 53 | } 54 | s := grpc.NewServer( 55 | // grpc.Creds(credentials.NewServerTLSFromCert(&insecure.Cert)), 56 | ) 57 | mesh.RegisterMeshServiceServer(s, &nsx-sm.Client{}) 58 | 59 | // Serve gRPC Server 60 | logrus.Infof("Serving gRPC on %s", addr) 61 | logrus.Fatal(s.Serve(lis)) 62 | } 63 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/layer5io/meshery-nsx-sm 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/Azure/go-autorest/autorest/adal v0.6.0 // indirect 7 | github.com/aspenmesh/nsx-sm-client-go v0.0.0-20190426173040-3e73c27b9ace 8 | github.com/aspenmesh/nsx-sm-vet v0.0.0-20190708155745-fac74e54e2e6 9 | github.com/cnf/structhash v0.0.0-20180104161610-62a607eb0224 // indirect 10 | github.com/ghodss/yaml v1.0.0 11 | github.com/gogo/protobuf v1.3.0 // indirect 12 | github.com/golang/protobuf v1.3.2 13 | github.com/googleapis/gnostic v0.3.1 // indirect 14 | github.com/gophercloud/gophercloud v0.4.0 // indirect 15 | github.com/hashicorp/golang-lru v0.5.3 // indirect 16 | github.com/imdario/mergo v0.3.7 // indirect 17 | github.com/json-iterator/go v1.1.7 // indirect 18 | github.com/modern-go/reflect2 v1.0.1 // indirect 19 | github.com/pkg/errors v0.8.1 20 | github.com/sirupsen/logrus v1.4.2 21 | github.com/spf13/pflag v1.0.3 // indirect 22 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect 23 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect 24 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 25 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect 26 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect 27 | golang.org/x/tools v0.0.0-20191005014404-c9f9432ec4b2 // indirect 28 | google.golang.org/grpc v1.23.0 29 | gopkg.in/inf.v0 v0.9.1 // indirect 30 | nsx-sm.io/api v0.0.0-20190905172106-906cbe6415a5 // indirect 31 | k8s.io/api v0.0.0-20190313235455-40a48860b5ab // indirect 32 | k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1 33 | k8s.io/client-go v11.0.0+incompatible 34 | k8s.io/klog v0.4.0 // indirect 35 | k8s.io/utils v0.0.0-20190829053155-3a4a5477acf8 // indirect 36 | sigs.k8s.io/yaml v1.1.0 // indirect 37 | ) 38 | -------------------------------------------------------------------------------- /img/readme/meshery-logo.svg: -------------------------------------------------------------------------------- 1 | Asset 3 -------------------------------------------------------------------------------- /nsx-sm/yaml.go: -------------------------------------------------------------------------------- 1 | package nsx-sm 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "io" 7 | ) 8 | 9 | // YAMLDecoder reads chunks of objects and returns ErrShortBuffer if 10 | // the data is not sufficient. 11 | // borrowed from APIMachinery 12 | type YAMLDecoder struct { 13 | r io.ReadCloser 14 | scanner *bufio.Scanner 15 | remaining []byte 16 | } 17 | 18 | // NewDocumentDecoder decodes YAML documents from the provided 19 | // stream in chunks by converting each document (as defined by 20 | // the YAML spec) into its own chunk. io.ErrShortBuffer will be 21 | // returned if the entire buffer could not be read to assist 22 | // the caller in framing the chunk. 23 | func NewDocumentDecoder(r io.ReadCloser) io.ReadCloser { 24 | b := make([]byte, 4096) 25 | scanner := bufio.NewScanner(r) 26 | scanner.Buffer(b, 256*1024) // overriding: the size of the buffer used was small when loading large sections from nsx-sm deployment yaml 27 | scanner.Split(splitYAMLDocument) 28 | return &YAMLDecoder{ 29 | r: r, 30 | scanner: scanner, 31 | } 32 | } 33 | 34 | // Read reads the previous slice into the buffer, or attempts to read 35 | // the next chunk. 36 | func (d *YAMLDecoder) Read(data []byte) (n int, err error) { 37 | left := len(d.remaining) 38 | if left == 0 { 39 | // return the next chunk from the stream 40 | if !d.scanner.Scan() { 41 | err := d.scanner.Err() 42 | if err == nil { 43 | err = io.EOF 44 | } 45 | return 0, err 46 | } 47 | out := d.scanner.Bytes() 48 | d.remaining = out 49 | left = len(out) 50 | } 51 | 52 | // fits within data 53 | if left <= len(data) { 54 | copy(data, d.remaining) 55 | d.remaining = nil 56 | return left, nil 57 | } 58 | 59 | // caller will need to reread 60 | copy(data, d.remaining[:len(data)]) 61 | d.remaining = d.remaining[len(data):] 62 | return len(data), io.ErrShortBuffer 63 | } 64 | 65 | // Close closes the decoder 66 | func (d *YAMLDecoder) Close() error { 67 | return d.r.Close() 68 | } 69 | 70 | const yamlSeparator = "\n---" 71 | const separator = "---" 72 | 73 | // splitYAMLDocument is a bufio.SplitFunc for splitting YAML streams into individual documents. 74 | func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) { 75 | if atEOF && len(data) == 0 { 76 | return 0, nil, nil 77 | } 78 | sep := len([]byte(yamlSeparator)) 79 | if i := bytes.Index(data, []byte(yamlSeparator)); i >= 0 { 80 | // We have a potential document terminator 81 | i += sep 82 | after := data[i:] 83 | if len(after) == 0 { 84 | // we can't read any more characters 85 | if atEOF { 86 | return len(data), data[:len(data)-sep], nil 87 | } 88 | return 0, nil, nil 89 | } 90 | if j := bytes.IndexByte(after, '\n'); j >= 0 { 91 | return i + j + 1, data[0 : i-sep], nil 92 | } 93 | return 0, nil, nil 94 | } 95 | // If we're at EOF, we have a final, non-terminated line. Return it. 96 | if atEOF { 97 | return len(data), data, nil 98 | } 99 | // Request more data. 100 | return 0, nil, nil 101 | } 102 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome 3 | # Comment to be posted to on first time issues 4 | newIssueWelcomeComment: > 5 | Thanks for opening this issue. A contributor will be by to give feedback soon. In the meantime, please review the [Meshery Community Welcome Guide](https://docs.meshery.io/project/contributing) and sure to join the [community Slack](http://slack.meshery.io/). 6 | # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome 7 | # Comment to be posted to on PRs from first time contributors in your repository 8 | newPRWelcomeComment: > 9 | Yay, your first pull request! :thumbsup: A contributor will be by to give feedback soon. In the meantime, please review the [Meshery Community Welcome Guide](https://docs.meshery.io/project/contributing) and sure to join the [community Slack](http://slack.meshery.io/). 10 | Be sure to double-check that you have signed your commits. Here are instructions for [making signing an implicit activity while peforming a commit](../CONTRIBUTING.md#signing-off-on-commits-developer-certificate-of-origin). 11 | #------------------------------------------------------------------------------- 12 | # Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge 13 | # Comment to be posted to on pull requests merged by a first time user 14 | firstPRMergeComment: > 15 | Thanks for your contribution to the Meshery community! :tada: 16 | 17 | 18 | 19 | 20 | Meshery Logo 21 | 22 | #------------------------------------------------------------------------------- 23 | # Configuration for request-info - https://github.com/behaviorbot/request-info 24 | # Comment to reply with 25 | requestInfoReplyComment: > 26 | Thanks for opening this issue. We welcome all input! If you could provide a little more information, this will greatly aid in its resolution. :thumbsup: 27 | # *OPTIONAL* Add a list of people whose Issues/PRs will not be commented on 28 | # keys must be GitHub usernames 29 | #requestInfoUserstoExclude: 30 | # - meshery/maintainers 31 | 32 | 33 | #------------------------------------------------------------------------------- 34 | # Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot 35 | # *Required* toxicity threshold between 0 and .99 with the higher numbers being the most toxic 36 | # Anything higher than this threshold will be marked as toxic and commented on 37 | sentimentBotToxicityThreshold: .9 38 | 39 | # *Required* Comment to reply with 40 | sentimentBotReplyComment: > 41 | Please be sure to review the code of conduct and be respectful of other users. // @meshery/maintainers 42 | -------------------------------------------------------------------------------- /img/readme/meshery-logo-light-text-side.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/readme/meshery-logo-dark-text-side.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nsx-sm/client.go: -------------------------------------------------------------------------------- 1 | // Copyright Meshery Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package nsx-sm 16 | 17 | import ( 18 | "time" 19 | 20 | "github.com/layer5io/meshery-nsx-sm/meshes" 21 | "github.com/sirupsen/logrus" 22 | "k8s.io/client-go/dynamic" 23 | "k8s.io/client-go/kubernetes" 24 | 25 | // auth is needed for initialization only 26 | _ "k8s.io/client-go/plugin/pkg/client/auth" 27 | "k8s.io/client-go/rest" 28 | "k8s.io/client-go/tools/clientcmd" 29 | 30 | "github.com/ghodss/yaml" 31 | ) 32 | 33 | // Client represents an nsx-sm client in Meshery 34 | type Client struct { 35 | config *rest.Config 36 | k8sClientset *kubernetes.Clientset 37 | k8sDynamicClient dynamic.Interface 38 | eventChan chan *meshes.EventsResponse 39 | 40 | nsx-smReleaseVersion string 41 | nsx-smReleaseDownloadURL string 42 | nsx-smReleaseUpdatedAt time.Time 43 | } 44 | 45 | func configClient(kubeconfig []byte, contextName string) (*rest.Config, error) { 46 | if len(kubeconfig) > 0 { 47 | ccfg, err := clientcmd.Load(kubeconfig) 48 | if err != nil { 49 | return nil, err 50 | } 51 | if contextName != "" { 52 | ccfg.CurrentContext = contextName 53 | } 54 | 55 | return clientcmd.NewDefaultClientConfig(*ccfg, &clientcmd.ConfigOverrides{}).ClientConfig() 56 | } 57 | return rest.InClusterConfig() 58 | } 59 | 60 | func newClient(kubeconfig []byte, contextName string) (*Client, error) { 61 | kubeconfig = monkeyPatchingToSupportInsecureConn(kubeconfig) 62 | client := Client{} 63 | config, err := configClient(kubeconfig, contextName) 64 | if err != nil { 65 | return nil, err 66 | } 67 | config.QPS = 100 68 | config.Burst = 200 69 | 70 | dynamicClient, err := dynamic.NewForConfig(config) 71 | if err != nil { 72 | return nil, err 73 | } 74 | client.k8sDynamicClient = dynamicClient 75 | 76 | k8sClientset, err := kubernetes.NewForConfig(config) 77 | if err != nil { 78 | return nil, err 79 | } 80 | client.k8sClientset = k8sClientset 81 | client.config = config 82 | 83 | return &client, nil 84 | } 85 | 86 | func monkeyPatchingToSupportInsecureConn(data []byte) []byte { 87 | config := map[string]interface{}{} 88 | if err := yaml.Unmarshal(data, &config); err != nil { 89 | logrus.Warn(err) 90 | return data // we will skip this process 91 | } 92 | // logrus.Infof("unmarshalled config: %+#v", config) 93 | clusters, ok := config["clusters"].([]interface{}) 94 | if !ok { 95 | logrus.Warn("unable to type cast clusters to a map array") 96 | return data 97 | } 98 | for _, clusterI := range clusters { 99 | cluster, ok := clusterI.(map[string]interface{}) 100 | if !ok { 101 | logrus.Warn("unable to type case individual cluster to a map") 102 | continue 103 | } 104 | indCluster, ok := cluster["cluster"].(map[string]interface{}) 105 | if !ok { 106 | logrus.Warn("unable to type case clusters.cluster to a map") 107 | continue 108 | } 109 | indCluster["insecure-skip-tls-verify"] = true // TODO: should we persist this back? 110 | delete(indCluster, "certificate-authority-data") 111 | delete(indCluster, "certificate-authority") 112 | } 113 | // logrus.Debugf("New config: %+#v", config) 114 | data1, err := yaml.Marshal(config) 115 | if err != nil { 116 | logrus.Warn(err) 117 | return data 118 | } 119 | return data1 120 | } 121 | -------------------------------------------------------------------------------- /nsx-sm/vet.go: -------------------------------------------------------------------------------- 1 | package nsx-sm 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | nsx-sminformer "github.com/aspenmesh/nsx-sm-client-go/pkg/client/informers/externalversions" 8 | "github.com/aspenmesh/nsx-sm-vet/pkg/nsx-smclient" 9 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter" 10 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/applabel" 11 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/conflictingvirtualservicehost" 12 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/danglingroutedestinationhost" 13 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/meshversion" 14 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/mtlsprobes" 15 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/podsinmesh" 16 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/serviceassociation" 17 | "github.com/aspenmesh/nsx-sm-vet/pkg/vetter/serviceportprefix" 18 | "github.com/layer5io/meshery-nsx-sm/meshes" 19 | "github.com/pkg/errors" 20 | "github.com/sirupsen/logrus" 21 | "k8s.io/client-go/informers" 22 | 23 | apiv1 "github.com/aspenmesh/nsx-sm-vet/api/v1" 24 | ) 25 | 26 | type metaInformerFactory struct { 27 | k8s informers.SharedInformerFactory 28 | nsx-sm nsx-sminformer.SharedInformerFactory 29 | } 30 | 31 | func (m *metaInformerFactory) K8s() informers.SharedInformerFactory { 32 | return m.k8s 33 | } 34 | func (m *metaInformerFactory) nsx-sm() nsx-sminformer.SharedInformerFactory { 35 | return m.nsx-sm 36 | } 37 | 38 | func (iClient *Client) runVet() error { 39 | nsx-smClient, err := nsx-smclient.New(iClient.config) 40 | if err != nil { 41 | err = errors.Wrap(err, "unable to create a new nsx-sm client") 42 | return err 43 | } 44 | 45 | kubeInformerFactory := informers.NewSharedInformerFactory(iClient.k8sClientset, 0) 46 | nsx-smInformerFactory := nsx-sminformer.NewSharedInformerFactory(nsx-smClient, 0) 47 | informerFactory := &metaInformerFactory{ 48 | k8s: kubeInformerFactory, 49 | nsx-sm: nsx-smInformerFactory, 50 | } 51 | 52 | vList := []vetter.Vetter{ 53 | vetter.Vetter(podsinmesh.NewVetter(informerFactory)), 54 | vetter.Vetter(meshversion.NewVetter(informerFactory)), 55 | vetter.Vetter(mtlsprobes.NewVetter(informerFactory)), 56 | vetter.Vetter(applabel.NewVetter(informerFactory)), 57 | vetter.Vetter(serviceportprefix.NewVetter(informerFactory)), 58 | vetter.Vetter(serviceassociation.NewVetter(informerFactory)), 59 | vetter.Vetter(danglingroutedestinationhost.NewVetter(informerFactory)), 60 | vetter.Vetter(conflictingvirtualservicehost.NewVetter(informerFactory)), 61 | } 62 | 63 | stopCh := make(chan struct{}) 64 | 65 | kubeInformerFactory.Start(stopCh) 66 | oks := kubeInformerFactory.WaitForCacheSync(stopCh) 67 | for inf, ok := range oks { 68 | if !ok { 69 | err := errors.Errorf("Failed to sync: %s", inf) 70 | logrus.Error(err) 71 | return err 72 | } 73 | } 74 | 75 | nsx-smInformerFactory.Start(stopCh) 76 | oks = nsx-smInformerFactory.WaitForCacheSync(stopCh) 77 | for inf, ok := range oks { 78 | if !ok { 79 | err := errors.Errorf("Failed to sync %s", inf) 80 | logrus.Error(err) 81 | return err 82 | } 83 | } 84 | close(stopCh) 85 | 86 | for _, v := range vList { 87 | nList, err := v.Vet() 88 | if err != nil { 89 | logrus.Debugf("Vetter: %s reported error: %s", v.Info().GetId(), err) 90 | iClient.eventChan <- &meshes.EventsResponse{ 91 | EventType: meshes.EventType_ERROR, 92 | Summary: fmt.Sprintf("Vetter: %s reported error", v.Info().GetId()), 93 | Details: err.Error(), 94 | } 95 | continue 96 | } 97 | if len(nList) > 0 { 98 | for i := range nList { 99 | var ts []string 100 | for k, v := range nList[i].Attr { 101 | ts = append(ts, "${"+k+"}", v) 102 | } 103 | r := strings.NewReplacer(ts...) 104 | summary := r.Replace(nList[i].GetSummary()) 105 | msg := r.Replace(nList[i].GetMsg()) 106 | // printNote(nList[i].GetLevel().String(), summary, msg) 107 | iClient.eventChan <- &meshes.EventsResponse{ 108 | EventType: convertVetLevelToMesheryLevel(nList[i].GetLevel()), 109 | Summary: summary, 110 | Details: msg, 111 | } 112 | } 113 | } else { 114 | logrus.Debugf("Vetter %s ran successfully and generated no notes", v.Info().GetId()) 115 | iClient.eventChan <- &meshes.EventsResponse{ 116 | EventType: meshes.EventType_INFO, 117 | Summary: fmt.Sprintf("Vetter: %s ran successfully", v.Info().GetId()), 118 | Details: "No notes generated", 119 | } 120 | } 121 | } 122 | return nil 123 | } 124 | 125 | func convertVetLevelToMesheryLevel(level apiv1.NoteLevel) meshes.EventType { 126 | switch level.String() { 127 | // case "INFO": 128 | // return 129 | case "WARNING": 130 | return meshes.EventType_WARN 131 | case "ERROR": 132 | return meshes.EventType_ERROR 133 | default: 134 | return meshes.EventType_INFO 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /nsx-sm/supported_ops.go: -------------------------------------------------------------------------------- 1 | // Copyright Meshery Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package nsx-sm 16 | 17 | import "github.com/layer5io/meshery-nsx-sm/meshes" 18 | 19 | type supportedOperation struct { 20 | // a friendly name 21 | name string 22 | // the template file name 23 | templateName string 24 | opType meshes.OpCategory 25 | } 26 | 27 | const ( 28 | customOpCommand = "custom" 29 | runVet = "nsx-sm_vet" 30 | installnsx-smCommand = "nsx-sm_install" 31 | installmTLSnsx-smCommand = "nsx-sm_mtls_install" 32 | installBookInfoCommand = "install_book_info" 33 | cbCommand = "cb1" 34 | installSMI = "install_smi" 35 | installHTTPBin = "install_http_bin" 36 | googleMSSampleApplication = "google_microservices_demo_application" 37 | bookInfoDefaultDestinationRules = "bookInfoDefaultDestinationRules" 38 | bookInfoRouteToV1AllServices = "bookInfoRouteToV1AllServices" 39 | bookInfoRouteToReviewsV2ForJason = "bookInfoRouteToReviewsV2ForJason" 40 | bookInfoCanary50pcReviewsV3 = "bookInfoCanary50pcReviewsV3" 41 | bookInfoCanary100pcReviewsV3 = "bookInfoCanary100pcReviewsV3" 42 | bookInfoInjectDelayForRatingsForJason = "bookInfoInjectDelayForRatingsForJason" 43 | bookInfoInjectHTTPAbortToRatingsForJason = "bookInfoInjectHTTPAbortToRatingsForJason" 44 | bookInfoProductPageCircuitBreaking = "bookInfoProductPageCircuitBreaking" 45 | ) 46 | 47 | var supportedOps = map[string]supportedOperation{ 48 | installnsx-smCommand: { 49 | name: "Latest nsx-sm without mTLS", 50 | // templateName: "install_nsx-sm.tmpl", 51 | opType: meshes.OpCategory_INSTALL, 52 | }, 53 | installmTLSnsx-smCommand: { 54 | name: "Latest nsx-sm with mTLS", 55 | opType: meshes.OpCategory_INSTALL, 56 | }, 57 | installBookInfoCommand: { 58 | name: "Book Info Application", 59 | // templateName: "install_nsx-sm.tmpl", 60 | opType: meshes.OpCategory_SAMPLE_APPLICATION, 61 | }, 62 | runVet: { 63 | name: "Run nsx-sm-vet", 64 | opType: meshes.OpCategory_VALIDATE, 65 | // templateName: "nsx-sm_vet.tmpl", 66 | // appLabel: "nsx-sm-vet", 67 | // returnLogs: true, 68 | }, 69 | cbCommand: { 70 | name: "Configure circuit breaker with only one connection", 71 | opType: meshes.OpCategory_CONFIGURE, 72 | templateName: "circuit_breaking.tmpl", 73 | }, 74 | bookInfoDefaultDestinationRules: { 75 | name: "Default Book info destination rules (defines subsets)", 76 | opType: meshes.OpCategory_CONFIGURE, 77 | }, 78 | bookInfoRouteToV1AllServices: { 79 | name: "Route traffic to V1 of all Book info services", 80 | opType: meshes.OpCategory_CONFIGURE, 81 | }, 82 | bookInfoRouteToReviewsV2ForJason: { 83 | name: "Route traffic to V2 of Book info reviews service for user Jason", 84 | opType: meshes.OpCategory_CONFIGURE, 85 | }, 86 | bookInfoCanary50pcReviewsV3: { 87 | name: "Route 50% of the traffic to Book info reviews V3", 88 | opType: meshes.OpCategory_CONFIGURE, 89 | }, 90 | bookInfoCanary100pcReviewsV3: { 91 | name: "Route 100% of the traffic to Book info reviews V3", 92 | opType: meshes.OpCategory_CONFIGURE, 93 | }, 94 | bookInfoInjectDelayForRatingsForJason: { 95 | name: "Inject a 7s delay in the traffic to Book info ratings service for user Jason", 96 | opType: meshes.OpCategory_CONFIGURE, 97 | }, 98 | bookInfoInjectHTTPAbortToRatingsForJason: { 99 | name: "Inject HTTP abort to Book info ratings service for user Jason", 100 | opType: meshes.OpCategory_CONFIGURE, 101 | }, 102 | bookInfoProductPageCircuitBreaking: { 103 | name: "Configure circuit breaking with max 1 request per connection and max 1 pending request to Book info productpage service", 104 | opType: meshes.OpCategory_CONFIGURE, 105 | templateName: "book_info_product_page_circuit_breaking.tmpl", 106 | }, 107 | installSMI: { 108 | name: "Service Mesh Interface (SMI) nsx-sm Adapter", 109 | opType: meshes.OpCategory_INSTALL, 110 | }, 111 | installHTTPBin: { 112 | name: "HTTPbin Application", 113 | templateName: "httpbin.yaml", 114 | opType: meshes.OpCategory_SAMPLE_APPLICATION, 115 | }, 116 | customOpCommand: { 117 | name: "Custom YAML", 118 | opType: meshes.OpCategory_CUSTOM, 119 | }, 120 | googleMSSampleApplication: { 121 | name: "Hipster Shop Application", 122 | opType: meshes.OpCategory_SAMPLE_APPLICATION, 123 | }, 124 | } 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 | 7 | Shows an illustrated light mode meshery logo in light color mode and a dark mode meshery logo dark color mode. 8 | 9 | 10 |

11 |
12 | 13 | # Meshery Adapter for Tanzu Service Mesh 14 | 15 | [![Docker Pulls](https://img.shields.io/docker/pulls/meshery/meshery-tanzu-sm.svg)](https://hub.docker.com/r/meshery/meshery-tanzu-sm) 16 | [![Go Report Card](https://goreportcard.com/badge/github.com/meshery/meshery-tanzu-sm)](https://goreportcard.com/report/github.com/meshery/meshery-tanzu-sm) 17 | [![Build Status](https://github.com/meshery/meshery-tanzu-sm/workflows/Meshery-Tanzusnx-SM/badge.svg)](https://github.com/meshery/meshery-tanzu-sm/actions) 18 | [![GitHub](https://img.shields.io/github/license/meshery/meshery-tanzu-sm.svg)](LICENSE) 19 | [![GitHub issues by-label](https://img.shields.io/github/issues/meshery/meshery-tanzu-sm/help%20wanted.svg)](https://github.com/issues?q=is%3Aopen%20is%3Aissue%20archived%3Afalse%20(org%3Ameshery%20OR%20org%3Aservice-mesh-performance%20OR%20org%3Aservice-mesh-patterns%20OR%20org%3Ameshery-extensions)%20label%3A%22help%20wanted%22) 20 | [![Website](https://img.shields.io/website/https/meshery.io/meshery.svg)](https://meshery.io/meshery/) 21 | [![Twitter Follow](https://img.shields.io/twitter/follow/lamesheryyer5.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=mesheryio) 22 | [![Slack](https://img.shields.io/badge/Slack-@meshery.svg?logo=slack)](https://slack.meshery.io) 23 | [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3564/badge)](https://bestpractices.coreinfrastructure.org/projects/3564) 24 | 25 |

26 |

Meshery

27 | Meshery - the Cloud Native Manager 30 | A self-service engineering platform, Meshery, is the open source, cloud native manager that enables the design and management of all Kubernetes-based infrastructure and applications (multi-cloud). Among other features, As an extensible platform, Meshery offers visual and collaborative GitOps, freeing you from the chains of YAML while managing Kubernetes multi-cluster deployments. 31 |

If you’re using Meshery or if you like the project, please star this repository to show your support! 🤩

32 |

33 | 34 |

35 |

Community and Contributing

36 | Our projects are community-built and welcome collaboration. 👍 Be sure to see the Meshery Community Welcome Guide for a tour of resources available to you and jump into our Slack! Contributors are expected to adhere to the CNCF Code of Conduct. 37 | 38 | 39 | 40 | 41 | 42 | 43 | Shows an illustrated light mode meshery logo in light color mode and a dark mode meshery logo dark color mode. 44 | 45 | 46 | 47 | Meshery Cloud Native Community 48 | 49 |

50 | ✔️ Join any or all of the weekly meetings on community calendar.
51 | ✔️ Watch community meeting recordings.
52 | ✔️ Fill-in a community member form to gain access to community resources.
53 | ✔️ Discuss in the Community Forum.
54 |

55 |

56 | Not sure where to start? Grab an open issue with the help-wanted label. 57 |

58 | 59 | 60 | **License** 61 | 62 | This repository and site are available as open source under the terms of the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0). 63 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: meshery-tanzu-sm 2 | on: 3 | push: 4 | branches: 5 | - '*' 6 | tags: 7 | - 'v*' 8 | pull_request: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | lint: 14 | name: Check & Review code 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Check out code 18 | uses: actions/checkout@master 19 | with: 20 | fetch-depth: 1 21 | - name: Setup Go 22 | uses: actions/setup-go@master 23 | with: 24 | go-version: ${{ secrets.GO_VERSION }} 25 | - run: GOPROXY=direct GOSUMDB=off go get -u golang.org/x/lint/golint; go list ./... | grep -v /vendor/ | xargs -L1 /home/runner/go/bin/golint -set_exit_status 26 | # error_check: 27 | # name: Error check 28 | # runs-on: ubuntu-latest 29 | # steps: 30 | # - name: Check out code 31 | # uses: actions/checkout@master 32 | # with: 33 | # fetch-depth: 1 34 | # - name: Setup Go 35 | # uses: actions/setup-go@master 36 | # with: 37 | # go-version: ${{ secrets.GO_VERSION }} 38 | # - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go get -u github.com/kisielk/errcheck; /home/runner/go/bin/errcheck ./... 39 | # static_check: 40 | # name: Static check 41 | # runs-on: ubuntu-latest 42 | # steps: 43 | # - name: Check out code 44 | # uses: actions/checkout@master 45 | # with: 46 | # fetch-depth: 1 47 | # - name: Setup Go 48 | # uses: actions/setup-go@master 49 | # with: 50 | # go-version: ${{ secrets.GO_VERSION }} 51 | # - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go get -u honnef.co/go/tools/cmd/staticcheck; /home/runner/go/bin/staticcheck -checks all ./... # https://staticcheck.io/docs/checks 52 | # vet: 53 | # name: Vet 54 | # runs-on: ubuntu-latest 55 | # steps: 56 | # - name: Check out code 57 | # uses: actions/checkout@master 58 | # with: 59 | # fetch-depth: 1 60 | # - name: Setup Go 61 | # uses: actions/setup-go@master 62 | # with: 63 | # go-version: ${{ secrets.GO_VERSION }} 64 | # - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go vet ./... 65 | # sec_check: 66 | # name: Security check 67 | # runs-on: ubuntu-latest 68 | # steps: 69 | # - name: Check out code 70 | # uses: actions/checkout@master 71 | # with: 72 | # fetch-depth: 1 73 | # - name: Setup Go 74 | # uses: actions/setup-go@master 75 | # with: 76 | # go-version: ${{ secrets.GO_VERSION }} 77 | # - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go get github.com/securego/gosec/cmd/gosec; /home/runner/go/bin/gosec ./... # https://github.com/securego/gosec 78 | # tests: 79 | # # needs: [lint, error_check, static_check, vet, sec_check] 80 | # name: Tests 81 | # runs-on: ubuntu-latest 82 | # steps: 83 | # - name: Check out code 84 | # uses: actions/checkout@master 85 | # with: 86 | # fetch-depth: 1 87 | # - name: Setup Go 88 | # uses: actions/setup-go@master 89 | # with: 90 | # go-version: ${{ secrets.GO_VERSION }} 91 | # - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go test ./... 92 | build: 93 | name: Build check 94 | runs-on: ubuntu-latest 95 | # needs: [lint, error_check, static_check, vet, sec_check, tests] 96 | steps: 97 | - name: Check out code 98 | uses: actions/checkout@master 99 | with: 100 | fetch-depth: 1 101 | - name: Setup Go 102 | uses: actions/setup-go@master 103 | with: 104 | go-version: ${{ secrets.GO_VERSION }} 105 | - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go get -u github.com/kisielk/errcheck; /home/runner/go/bin/errcheck -tags draft ./... 106 | docker: 107 | name: Docker build and push 108 | runs-on: ubuntu-latest 109 | # needs: [build, build_release] 110 | steps: 111 | - name: Check out code 112 | if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() 113 | uses: actions/checkout@master 114 | with: 115 | fetch-depth: 1 116 | - name: Docker login 117 | if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() 118 | uses: azure/container-actions/docker-login@master 119 | with: 120 | username: ${{ secrets.DOCKER_USERNAME }} 121 | password: ${{ secrets.DOCKER_PASSWORD }} 122 | - name: Docker build & tag 123 | if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() 124 | run: | 125 | DOCKER_BUILDKIT=1 docker build --no-cache -t ${{ secrets.IMAGE_NAME }}:stable-latest . 126 | docker tag ${{ secrets.IMAGE_NAME }}:stable-latest ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_REF/refs\/tags\//} 127 | docker tag ${{ secrets.IMAGE_NAME }}:stable-latest ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_SHA::7} 128 | - name: Docker push 129 | if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() 130 | run: | 131 | docker push ${{ secrets.IMAGE_NAME }}:stable-latest 132 | docker push ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_REF/refs\/tags\//} 133 | docker push ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_SHA::7} 134 | - name: Docker Hub Description 135 | if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() 136 | uses: peter-evans/dockerhub-description@2.0.0 137 | env: 138 | DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }} 139 | DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} 140 | DOCKERHUB_REPOSITORY: ${{ secrets.IMAGE_NAME }} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright Meshery Authors 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /nsx-sm/install-nsx-sm.go: -------------------------------------------------------------------------------- 1 | package nsx-sm 2 | 3 | import ( 4 | "archive/tar" 5 | "compress/gzip" 6 | "encoding/json" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "net/http" 11 | "os" 12 | "path" 13 | "path/filepath" 14 | "regexp" 15 | "strings" 16 | "time" 17 | 18 | "github.com/pkg/errors" 19 | "github.com/sirupsen/logrus" 20 | ) 21 | 22 | const ( 23 | repoURL = "https://api.github.com/repos/nsx-sm/nsx-sm/releases/latest" 24 | urlSuffix = "-linux.tar.gz" 25 | crdPattern = "crd(.*)yaml" 26 | cachePeriod = 6 * time.Hour 27 | ) 28 | 29 | var ( 30 | localByPassFile = "/app/nsx-sm.tar.gz" 31 | 32 | localFile = path.Join(os.TempDir(), "nsx-sm.tar.gz") 33 | destinationFolder = path.Join(os.TempDir(), "nsx-sm") 34 | basePath = path.Join(destinationFolder, "%s") 35 | installFile = path.Join(basePath, "install/kubernetes/nsx-sm-demo.yaml") 36 | installWithmTLSFile = path.Join(basePath, "install/kubernetes/nsx-sm-demo-auth.yaml") 37 | bookInfoInstallFile = path.Join(basePath, "samples/bookinfo/platform/kube/bookinfo.yaml") 38 | bookInfoGatewayInstallFile = path.Join(basePath, "samples/bookinfo/networking/bookinfo-gateway.yaml") 39 | crdFolder = path.Join(basePath, "install/kubernetes/helm/nsx-sm-init/files/") 40 | 41 | defaultBookInfoDestRulesFile = path.Join(basePath, "samples/bookinfo/networking/destination-rule-all-mtls.yaml") 42 | bookInfoRouteToV1AllServicesFile = path.Join(basePath, "samples/bookinfo/networking/virtual-service-all-v1.yaml") 43 | bookInfoRouteToReviewsV2ForJasonFile = path.Join(basePath, "samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml") 44 | bookInfoCanary50pcReviewsV3File = path.Join(basePath, "samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml") 45 | bookInfoCanary100pcReviewsV3File = path.Join(basePath, "samples/bookinfo/networking/virtual-service-reviews-v3.yaml") 46 | bookInfoInjectDelayForRatingsForJasonFile = path.Join(basePath, "samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml") 47 | bookInfoInjectHTTPAbortToRatingsForJasonFile = path.Join(basePath, "samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml") 48 | ) 49 | 50 | type apiInfo struct { 51 | TagName string `json:"tag_name,omitempty"` 52 | PreRelease bool `json:"prerelease,omitempty"` 53 | Assets []*asset `json:"assets,omitempty"` 54 | } 55 | 56 | type asset struct { 57 | Name string `json:"name,omitempty"` 58 | State string `json:"state,omitempty"` 59 | DownloadURL string `json:"browser_download_url,omitempty"` 60 | } 61 | 62 | func (iClient *Client) getLatestReleaseURL() error { 63 | if iClient.nsx-smReleaseDownloadURL == "" || time.Since(iClient.nsx-smReleaseUpdatedAt) > cachePeriod { 64 | logrus.Debugf("API info url: %s", repoURL) 65 | resp, err := http.Get(repoURL) 66 | if err != nil { 67 | err = errors.Wrapf(err, "error getting latest version info") 68 | logrus.Error(err) 69 | return err 70 | } 71 | defer resp.Body.Close() 72 | 73 | if resp.StatusCode != http.StatusOK { 74 | err = fmt.Errorf("unable to fetch release info due to an unexpected status code: %d", resp.StatusCode) 75 | logrus.Error(err) 76 | return err 77 | } 78 | 79 | body, err := ioutil.ReadAll(resp.Body) 80 | if err != nil { 81 | err = errors.Wrapf(err, "error parsing response body") 82 | logrus.Error(err) 83 | return err 84 | } 85 | // logrus.Debugf("Raw api info: %s", body) 86 | result := &apiInfo{} 87 | err = json.Unmarshal(body, result) 88 | if err != nil { 89 | err = errors.Wrapf(err, "error unmarshalling response body") 90 | logrus.Error(err) 91 | return err 92 | } 93 | logrus.Debugf("retrieved api info: %+#v", result) 94 | if result != nil && result.Assets != nil && len(result.Assets) > 0 { 95 | for _, asset := range result.Assets { 96 | if strings.HasSuffix(asset.Name, urlSuffix) { 97 | iClient.nsx-smReleaseVersion = strings.Replace(asset.Name, urlSuffix, "", -1) 98 | iClient.nsx-smReleaseDownloadURL = asset.DownloadURL 99 | iClient.nsx-smReleaseUpdatedAt = time.Now() 100 | return nil 101 | } 102 | } 103 | } 104 | err = errors.New("unable to extract the download URL") 105 | logrus.Error(err) 106 | return err 107 | } 108 | return nil 109 | } 110 | 111 | func (iClient *Client) downloadFile(localFile string) error { 112 | dFile, err := os.Create(localFile) 113 | if err != nil { 114 | err = errors.Wrapf(err, "unable to create a file on the filesystem at %s", localFile) 115 | logrus.Error(err) 116 | return err 117 | } 118 | defer dFile.Close() 119 | 120 | resp, err := http.Get(iClient.nsx-smReleaseDownloadURL) 121 | if err != nil { 122 | err = errors.Wrapf(err, "unable to download the file from URL: %s", iClient.nsx-smReleaseDownloadURL) 123 | logrus.Error(err) 124 | return err 125 | } 126 | defer resp.Body.Close() 127 | 128 | if resp.StatusCode != http.StatusOK { 129 | err = fmt.Errorf("unable to download the file from URL: %s, status: %s", iClient.nsx-smReleaseDownloadURL, resp.Status) 130 | logrus.Error(err) 131 | return err 132 | } 133 | 134 | _, err = io.Copy(dFile, resp.Body) 135 | if err != nil { 136 | err = errors.Wrapf(err, "unable to write the downloaded file to the file system at %s", localFile) 137 | logrus.Error(err) 138 | return err 139 | } 140 | return nil 141 | } 142 | 143 | func (iClient *Client) untarPackage(destination, fileToUntar string) error { 144 | lFile, err := os.Open(fileToUntar) 145 | if err != nil { 146 | err = errors.Wrapf(err, "unable to read the local file %s", fileToUntar) 147 | logrus.Error(err) 148 | return err 149 | } 150 | 151 | gzReader, err := gzip.NewReader(lFile) 152 | if err != nil { 153 | err = errors.Wrap(err, "unable to load the file into a gz reader") 154 | logrus.Error(err) 155 | return err 156 | } 157 | defer gzReader.Close() 158 | 159 | tarReader := tar.NewReader(gzReader) 160 | for { 161 | header, err := tarReader.Next() 162 | switch { 163 | case err == io.EOF: 164 | return nil 165 | case err != nil: 166 | err = errors.Wrap(err, "error during untar") 167 | logrus.Error(err) 168 | return err 169 | case header == nil: 170 | continue 171 | } 172 | 173 | fileInLoop := filepath.Join(destination, header.Name) 174 | switch header.Typeflag { 175 | case tar.TypeDir: 176 | if _, err := os.Stat(fileInLoop); err != nil { 177 | if err := os.MkdirAll(fileInLoop, 0755); err != nil { 178 | err = errors.Wrapf(err, "error creating directory %s", fileInLoop) 179 | logrus.Error(err) 180 | return err 181 | } 182 | } 183 | case tar.TypeReg: 184 | fileAtLoc, err := os.OpenFile(fileInLoop, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) 185 | if err != nil { 186 | err = errors.Wrapf(err, "error opening file %s", fileInLoop) 187 | logrus.Error(err) 188 | return err 189 | } 190 | 191 | if _, err := io.Copy(fileAtLoc, tarReader); err != nil { 192 | err = errors.Wrapf(err, "error writing file %s", fileInLoop) 193 | logrus.Error(err) 194 | return err 195 | } 196 | fileAtLoc.Close() 197 | } 198 | } 199 | } 200 | 201 | func (iClient *Client) downloadnsx-sm() (string, error) { 202 | var fileName string 203 | _, err := os.Stat(localByPassFile) 204 | if err != nil { 205 | logrus.Debug("preparing to download the latest nsx-sm release") 206 | err := iClient.getLatestReleaseURL() 207 | if err != nil { 208 | return "", err 209 | } 210 | fileName = iClient.nsx-smReleaseVersion 211 | downloadURL := iClient.nsx-smReleaseDownloadURL 212 | logrus.Debugf("retrieved latest file name: %s and download url: %s", fileName, downloadURL) 213 | 214 | proceedWithDownload := true 215 | 216 | lFileStat, err := os.Stat(localFile) 217 | if err == nil { 218 | if time.Since(lFileStat.ModTime()) > cachePeriod { 219 | proceedWithDownload = true 220 | } else { 221 | proceedWithDownload = false 222 | } 223 | } 224 | 225 | if proceedWithDownload { 226 | if err = iClient.downloadFile(localFile); err != nil { 227 | return "", err 228 | } 229 | logrus.Debug("package successfully downloaded, now unzipping . . .") 230 | } 231 | } else { 232 | localFile = localByPassFile 233 | fileName = os.Getenv("nsx-sm_VERSION") 234 | logrus.Debugf("using local bypass file: %s & version name from env: %s", localFile, fileName) 235 | } 236 | if err = iClient.untarPackage(destinationFolder, localFile); err != nil { 237 | return "", err 238 | } 239 | logrus.Debug("successfully unzipped") 240 | return fileName, nil 241 | } 242 | 243 | func (iClient *Client) getnsx-smComponentYAML(fileName string) (string, error) { 244 | specificVersionName, err := iClient.downloadnsx-sm() 245 | if err != nil { 246 | return "", err 247 | } 248 | installFileLoc := fmt.Sprintf(fileName, specificVersionName) 249 | logrus.Debugf("checking if install file exists at path: %s", installFileLoc) 250 | _, err = os.Stat(installFileLoc) 251 | if err != nil { 252 | if os.IsNotExist(err) { 253 | logrus.Error(err) 254 | return "", err 255 | } 256 | err = errors.Wrap(err, "unknown error") 257 | logrus.Error(err) 258 | return "", err 259 | } 260 | fileContents, err := ioutil.ReadFile(installFileLoc) 261 | if err != nil { 262 | err = errors.Wrap(err, "unable to read file") 263 | logrus.Error(err) 264 | return "", err 265 | } 266 | return string(fileContents), nil 267 | } 268 | 269 | func (iClient *Client) getCRDsYAML() ([]string, error) { 270 | res := []string{} 271 | 272 | rEx, err := regexp.Compile(crdPattern) 273 | if err != nil { 274 | err = errors.Wrap(err, "unable to compile crd pattern") 275 | logrus.Error(err) 276 | return nil, err 277 | } 278 | 279 | specificVersionName, err := iClient.downloadnsx-sm() 280 | if err != nil { 281 | return nil, err 282 | } 283 | startFolder := fmt.Sprintf(crdFolder, specificVersionName) 284 | err = filepath.Walk(startFolder, func(currentPath string, info os.FileInfo, err error) error { 285 | if err == nil && rEx.MatchString(info.Name()) { 286 | contents, err := ioutil.ReadFile(currentPath) 287 | if err != nil { 288 | err = errors.Wrap(err, "unable to read file") 289 | logrus.Error(err) 290 | return err 291 | } 292 | res = append(res, string(contents)) 293 | } 294 | return nil 295 | }) 296 | if err != nil { 297 | err = errors.Wrap(err, "unable to read the directory") 298 | logrus.Error(err) 299 | return nil, err 300 | } 301 | return res, nil 302 | } 303 | 304 | func (iClient *Client) getLatestnsx-smYAML(installmTLS bool) (string, error) { 305 | if installmTLS { 306 | return iClient.getnsx-smComponentYAML(installWithmTLSFile) 307 | } 308 | return iClient.getnsx-smComponentYAML(installFile) 309 | } 310 | 311 | func (iClient *Client) getBookInfoAppYAML() (string, error) { 312 | return iClient.getnsx-smComponentYAML(bookInfoInstallFile) 313 | } 314 | 315 | func (iClient *Client) getBookInfoGatewayYAML() (string, error) { 316 | return iClient.getnsx-smComponentYAML(bookInfoGatewayInstallFile) 317 | } 318 | 319 | func (iClient *Client) getBookInfoDefaultDesinationRulesYAML() (string, error) { 320 | return iClient.getnsx-smComponentYAML(defaultBookInfoDestRulesFile) 321 | } 322 | 323 | func (iClient *Client) getBookInfoRouteToV1AllServicesYAML() (string, error) { 324 | return iClient.getnsx-smComponentYAML(bookInfoRouteToV1AllServicesFile) 325 | } 326 | 327 | func (iClient *Client) getBookInfoRouteToReviewsV2ForJasonFile() (string, error) { 328 | return iClient.getnsx-smComponentYAML(bookInfoRouteToReviewsV2ForJasonFile) 329 | } 330 | 331 | func (iClient *Client) getBookInfoCanary50pcReviewsV3File() (string, error) { 332 | return iClient.getnsx-smComponentYAML(bookInfoCanary50pcReviewsV3File) 333 | } 334 | 335 | func (iClient *Client) getBookInfoCanary100pcReviewsV3File() (string, error) { 336 | return iClient.getnsx-smComponentYAML(bookInfoCanary100pcReviewsV3File) 337 | } 338 | 339 | func (iClient *Client) getBookInfoInjectDelayForRatingsForJasonFile() (string, error) { 340 | return iClient.getnsx-smComponentYAML(bookInfoInjectDelayForRatingsForJasonFile) 341 | } 342 | 343 | func (iClient *Client) getBookInfoInjectHTTPAbortToRatingsForJasonFile() (string, error) { 344 | return iClient.getnsx-smComponentYAML(bookInfoInjectHTTPAbortToRatingsForJasonFile) 345 | } 346 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | github.com/Azure/go-autorest v13.0.0+incompatible h1:56c11ykhsFSPNNQuS73Ri8h/ezqVhr2h6t9LJIEKVO0= 5 | github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= 6 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 7 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 8 | github.com/Azure/go-autorest/autorest/adal v0.6.0 h1:UCTq22yE3RPgbU/8u4scfnnzuCW6pwQ9n+uBtV78ouo= 9 | github.com/Azure/go-autorest/autorest/adal v0.6.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= 10 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 11 | github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= 12 | github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= 13 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 14 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 15 | github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= 16 | github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= 17 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 18 | github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= 19 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 20 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 21 | github.com/aspenmesh/nsx-sm-client-go v0.0.0-20190426173040-3e73c27b9ace h1:m+Xk2zXjEtnTGA4T3zb4+avMrIq6DBMqFJM3FcjGji0= 22 | github.com/aspenmesh/nsx-sm-client-go v0.0.0-20190426173040-3e73c27b9ace/go.mod h1:HbtpC/r+MCS1vrS/OIs5vLVohdIh9KgX1utxg+fJ8WE= 23 | github.com/aspenmesh/nsx-sm-vet v0.0.0-20190708155745-fac74e54e2e6 h1:kqFjAq0OKfwrqOASkZ3OhEQQGDUsFw5zwBEHsROGoNI= 24 | github.com/aspenmesh/nsx-sm-vet v0.0.0-20190708155745-fac74e54e2e6/go.mod h1:8hVDM8l0fEURMlC806jrymafA2y9ty0tSmkx6KWuSSI= 25 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 26 | github.com/cnf/structhash v0.0.0-20180104161610-62a607eb0224 h1:rnCKRrdSBqc061l0CDuYB+7X3w6w8IK/VCSChJXv62g= 27 | github.com/cnf/structhash v0.0.0-20180104161610-62a607eb0224/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= 28 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 29 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 30 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 31 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 32 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 33 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 34 | github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= 35 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 36 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 37 | github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 38 | github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= 39 | github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 40 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 41 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 42 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 43 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 44 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 45 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 46 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 47 | github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= 48 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 49 | github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= 50 | github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= 51 | github.com/gophercloud/gophercloud v0.4.0 h1:4iXQnHF7LKOl7ncQsRibnUmfx/unxT3rLAniYRB8kQQ= 52 | github.com/gophercloud/gophercloud v0.4.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 53 | github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= 54 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 55 | github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= 56 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 57 | github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= 58 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 59 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 60 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 61 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 62 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 63 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 64 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 65 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 66 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 67 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 68 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 69 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 70 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 71 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 72 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 73 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 74 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 75 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 76 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 77 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 78 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 79 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 80 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 81 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 82 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 83 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= 84 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 85 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0= 86 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 87 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 88 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 89 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 90 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 91 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 92 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 93 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 94 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= 95 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 96 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 97 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 98 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 99 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 100 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 101 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 102 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 103 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 104 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 105 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= 106 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 107 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 108 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 109 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= 110 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 111 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 112 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 113 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A= 114 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 115 | golang.org/x/tools v0.0.0-20191005014404-c9f9432ec4b2 h1:cizXZUfmWsxq3+I8k+qEgLy3QlTEC1UoAvkaPMpTAmA= 116 | golang.org/x/tools v0.0.0-20191005014404-c9f9432ec4b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 117 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 118 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 119 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 120 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= 121 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 122 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 123 | google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= 124 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 125 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 126 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 127 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 128 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 129 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 130 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 131 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 132 | nsx-sm.io/api v0.0.0-20190905172106-906cbe6415a5 h1:FEDTpBQs8Qs0Upw7WeOZjyylwxP6rWcUmm5dquy3Dmo= 133 | nsx-sm.io/api v0.0.0-20190905172106-906cbe6415a5/go.mod h1:42cBjnu/rTJcCaKi8nLdIvq0n71RcLrkgZ9IQSvDdSQ= 134 | nsx-sm.io/gogo-genproto v0.0.0-20190731221249-06e20ada0df2/go.mod h1:IjvrbUlRbbw4JCpsgvgihcz9USUwEoNTL/uwMtyV5yk= 135 | k8s.io/api v0.0.0-20190313235455-40a48860b5ab h1:DG9A67baNpoeweOy2spF1OWHhnVY5KR7/Ek/+U1lVZc= 136 | k8s.io/api v0.0.0-20190313235455-40a48860b5ab/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= 137 | k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1 h1:IS7K02iBkQXpCeieSiyJjGoLSdVOv2DbPaWHJ+ZtgKg= 138 | k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= 139 | k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o= 140 | k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= 141 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 142 | k8s.io/klog v0.4.0 h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ= 143 | k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 144 | k8s.io/utils v0.0.0-20190829053155-3a4a5477acf8 h1:khtxGxwSe3nyReEEggzTwQigMT3g40enrlivMlMeaGY= 145 | k8s.io/utils v0.0.0-20190829053155-3a4a5477acf8/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 146 | sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= 147 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 148 | -------------------------------------------------------------------------------- /.github/welcome/Meshery-celebration-Dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/welcome/Meshery-celebration-Light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nsx-sm/nsx-sm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Layer5.io 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package nsx-sm 16 | 17 | import ( 18 | "bytes" 19 | "context" 20 | "fmt" 21 | "io" 22 | "io/ioutil" 23 | "net/http" 24 | "path" 25 | "strings" 26 | "text/template" 27 | "time" 28 | 29 | "github.com/ghodss/yaml" 30 | "github.com/layer5io/meshery-nsx-sm/meshes" 31 | "github.com/pkg/errors" 32 | "github.com/sirupsen/logrus" 33 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 34 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 35 | "k8s.io/apimachinery/pkg/runtime" 36 | "k8s.io/apimachinery/pkg/runtime/schema" 37 | ) 38 | 39 | const ( 40 | hipsterShopnsx-smManifestsURL = "https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/master/release/nsx-sm-manifests.yaml" 41 | hipsterShopKubernetesManifestsURL = "https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/master/release/kubernetes-manifests.yaml" 42 | ) 43 | 44 | //CreateMeshInstance is called from UI 45 | func (iClient *Client) CreateMeshInstance(_ context.Context, k8sReq *meshes.CreateMeshInstanceRequest) (*meshes.CreateMeshInstanceResponse, error) { 46 | var k8sConfig []byte 47 | contextName := "" 48 | if k8sReq != nil { 49 | k8sConfig = k8sReq.K8SConfig 50 | contextName = k8sReq.ContextName 51 | } 52 | // logrus.Debugf("received k8sConfig: %s", k8sConfig) 53 | logrus.Debugf("received contextName: %s", contextName) 54 | 55 | ic, err := newClient(k8sConfig, contextName) 56 | if err != nil { 57 | err = errors.Wrapf(err, "unable to create a new nsx-sm client") 58 | logrus.Error(err) 59 | return nil, err 60 | } 61 | iClient.k8sClientset = ic.k8sClientset 62 | iClient.k8sDynamicClient = ic.k8sDynamicClient 63 | iClient.eventChan = make(chan *meshes.EventsResponse, 100) 64 | iClient.config = ic.config 65 | return &meshes.CreateMeshInstanceResponse{}, nil 66 | } 67 | 68 | func (iClient *Client) createResource(ctx context.Context, res schema.GroupVersionResource, data *unstructured.Unstructured) error { 69 | _, err := iClient.k8sDynamicClient.Resource(res).Namespace(data.GetNamespace()).Create(data, metav1.CreateOptions{}) 70 | if err != nil { 71 | if strings.Contains(err.Error(), "already exists") { 72 | // if err1 := iClient.deleteResource(ctx, res, data); err1 != nil { 73 | 74 | // } 75 | return errors.Wrap(err, "resource already exists") 76 | } 77 | err = errors.Wrapf(err, "unable to create the requested resource, attempting operation without namespace") 78 | logrus.Warn(err) 79 | if _, err = iClient.k8sDynamicClient.Resource(res).Create(data, metav1.CreateOptions{}); err != nil { 80 | if strings.Contains(err.Error(), "already exists") { 81 | return errors.Wrap(err, "resource already exists") 82 | } 83 | err = errors.Wrapf(err, "unable to create the requested resource, attempting to update") 84 | logrus.Error(err) 85 | return err 86 | } 87 | } 88 | logrus.Infof("Created Resource of type: %s and name: %s", data.GetKind(), data.GetName()) 89 | return nil 90 | } 91 | 92 | func (iClient *Client) deleteResource(ctx context.Context, res schema.GroupVersionResource, data *unstructured.Unstructured) error { 93 | if iClient.k8sDynamicClient == nil { 94 | return errors.New("mesh client has not been created") 95 | } 96 | 97 | if res.Resource == "namespaces" && data.GetName() == "default" { // skipping deletion of default namespace 98 | return nil 99 | } 100 | 101 | // in the case with deployments, have to scale it down to 0 first and then delete. . . or else RS and pods will be left behind 102 | if res.Resource == "deployments" { 103 | data1, err := iClient.getResource(ctx, res, data) 104 | if err != nil { 105 | return err 106 | } 107 | depl := data1.UnstructuredContent() 108 | spec1 := depl["spec"].(map[string]interface{}) 109 | spec1["replicas"] = 0 110 | data1.SetUnstructuredContent(depl) 111 | if err = iClient.updateResource(ctx, res, data1); err != nil { 112 | return err 113 | } 114 | } 115 | 116 | err := iClient.k8sDynamicClient.Resource(res).Namespace(data.GetNamespace()).Delete(data.GetName(), &metav1.DeleteOptions{}) 117 | if err != nil { 118 | err = errors.Wrapf(err, "unable to delete the requested resource, attempting operation without namespace") 119 | logrus.Warn(err) 120 | 121 | err := iClient.k8sDynamicClient.Resource(res).Delete(data.GetName(), &metav1.DeleteOptions{}) 122 | if err != nil { 123 | err = errors.Wrapf(err, "unable to delete the requested resource") 124 | logrus.Error(err) 125 | return err 126 | } 127 | } 128 | logrus.Infof("Deleted Resource of type: %s and name: %s", data.GetKind(), data.GetName()) 129 | return nil 130 | } 131 | 132 | func (iClient *Client) getResource(ctx context.Context, res schema.GroupVersionResource, data *unstructured.Unstructured) (*unstructured.Unstructured, error) { 133 | data1, err := iClient.k8sDynamicClient.Resource(res).Namespace(data.GetNamespace()).Get(data.GetName(), metav1.GetOptions{}) 134 | if err != nil { 135 | err = errors.Wrap(err, "unable to retrieve the resource with a matching name, attempting operation without namespace") 136 | logrus.Warn(err) 137 | 138 | data1, err = iClient.k8sDynamicClient.Resource(res).Get(data.GetName(), metav1.GetOptions{}) 139 | if err != nil { 140 | err = errors.Wrap(err, "unable to retrieve the resource with a matching name, while attempting to apply the config") 141 | logrus.Error(err) 142 | return nil, err 143 | } 144 | } 145 | logrus.Infof("Retrieved Resource of type: %s and name: %s", data.GetKind(), data.GetName()) 146 | return data1, nil 147 | } 148 | 149 | func (iClient *Client) updateResource(ctx context.Context, res schema.GroupVersionResource, data *unstructured.Unstructured) error { 150 | if _, err := iClient.k8sDynamicClient.Resource(res).Namespace(data.GetNamespace()).Update(data, metav1.UpdateOptions{}); err != nil { 151 | if strings.Contains(err.Error(), "the server does not allow this method on the requested resource") { 152 | logrus.Error(err) 153 | return err 154 | } 155 | err = errors.Wrap(err, "unable to update resource with the given name, attempting operation without namespace") 156 | logrus.Warn(err) 157 | 158 | if _, err = iClient.k8sDynamicClient.Resource(res).Update(data, metav1.UpdateOptions{}); err != nil { 159 | if strings.Contains(err.Error(), "the server does not allow this method on the requested resource") { 160 | logrus.Error(err) 161 | return err 162 | } 163 | err = errors.Wrap(err, "unable to update resource with the given name, while attempting to apply the config") 164 | logrus.Error(err) 165 | return err 166 | } 167 | } 168 | logrus.Infof("Updated Resource of type: %s and name: %s", data.GetKind(), data.GetName()) 169 | return nil 170 | } 171 | 172 | // MeshName just returns the name of the mesh the client is representing 173 | func (iClient *Client) MeshName(context.Context, *meshes.MeshNameRequest) (*meshes.MeshNameResponse, error) { 174 | return &meshes.MeshNameResponse{Name: "nsx-sm"}, nil 175 | } 176 | 177 | func (iClient *Client) applyRulePayload(ctx context.Context, namespace string, newBytes []byte, delete, isCustomOp bool) error { 178 | if iClient.k8sDynamicClient == nil { 179 | return errors.New("mesh client has not been created") 180 | } 181 | // logrus.Debugf("received yaml bytes: %s", newBytes) 182 | jsonBytes, err := yaml.YAMLToJSON(newBytes) 183 | if err != nil { 184 | err = errors.Wrapf(err, "unable to convert yaml to json") 185 | logrus.Error(err) 186 | return err 187 | } 188 | // logrus.Debugf("created json: %s, length: %d", jsonBytes, len(jsonBytes)) 189 | if len(jsonBytes) > 5 { // attempting to skip 'null' json 190 | data := &unstructured.Unstructured{} 191 | err = data.UnmarshalJSON(jsonBytes) 192 | if err != nil { 193 | err = errors.Wrapf(err, "unable to unmarshal json created from yaml") 194 | logrus.Error(err) 195 | return err 196 | } 197 | if data.IsList() { 198 | err = data.EachListItem(func(r runtime.Object) error { 199 | dataL, _ := r.(*unstructured.Unstructured) 200 | return iClient.executeRule(ctx, dataL, namespace, delete, isCustomOp) 201 | }) 202 | return err 203 | } 204 | return iClient.executeRule(ctx, data, namespace, delete, isCustomOp) 205 | } 206 | return nil 207 | } 208 | 209 | func (iClient *Client) executeRule(ctx context.Context, data *unstructured.Unstructured, namespace string, delete, isCustomOp bool) error { 210 | // logrus.Debug("========================================================") 211 | // logrus.Debugf("Received data: %+#v", data) 212 | if namespace != "" { 213 | data.SetNamespace(namespace) 214 | } 215 | groupVersion := strings.Split(data.GetAPIVersion(), "/") 216 | logrus.Debugf("groupVersion: %v", groupVersion) 217 | var group, version string 218 | if len(groupVersion) == 2 { 219 | group = groupVersion[0] 220 | version = groupVersion[1] 221 | } else if len(groupVersion) == 1 { 222 | version = groupVersion[0] 223 | } 224 | 225 | kind := strings.ToLower(data.GetKind()) 226 | switch kind { 227 | case "logentry": 228 | kind = "logentries" 229 | case "kubernetes": 230 | kind = "kuberneteses" 231 | case "podsecuritypolicy": 232 | kind = "podsecuritypolicies" 233 | case "serviceentry": 234 | kind = "serviceentries" 235 | default: 236 | kind += "s" 237 | } 238 | 239 | res := schema.GroupVersionResource{ 240 | Group: group, 241 | Version: version, 242 | Resource: kind, 243 | } 244 | logrus.Debugf("Computed Resource: %+#v", res) 245 | 246 | if delete { 247 | return iClient.deleteResource(ctx, res, data) 248 | } 249 | trackRetry := 0 250 | RETRY: 251 | if err := iClient.createResource(ctx, res, data); err != nil { 252 | if isCustomOp { 253 | if err := iClient.deleteResource(ctx, res, data); err != nil { 254 | return err 255 | } 256 | time.Sleep(time.Second) 257 | if err := iClient.createResource(ctx, res, data); err != nil { 258 | return err 259 | } 260 | // data1, err := iClient.getResource(ctx, res, data) 261 | // if err != nil { 262 | // return err 263 | // } 264 | // if err = iClient.updateResource(ctx, res, data1); err != nil { 265 | // return err 266 | // } 267 | } else { 268 | data1, err := iClient.getResource(ctx, res, data) 269 | if err != nil { 270 | return err 271 | } 272 | data.SetCreationTimestamp(data1.GetCreationTimestamp()) 273 | data.SetGenerateName(data1.GetGenerateName()) 274 | data.SetGeneration(data1.GetGeneration()) 275 | data.SetSelfLink(data1.GetSelfLink()) 276 | data.SetResourceVersion(data1.GetResourceVersion()) 277 | // data.DeepCopyInto(data1) 278 | if err = iClient.updateResource(ctx, res, data); err != nil { 279 | if strings.Contains(err.Error(), "the server does not allow this method on the requested resource") { 280 | logrus.Info("attempting to delete resource. . . ") 281 | iClient.deleteResource(ctx, res, data) 282 | trackRetry++ 283 | if trackRetry <= 3 { 284 | goto RETRY 285 | } // else return error 286 | } 287 | return err 288 | } 289 | // return err 290 | } 291 | } 292 | return nil 293 | } 294 | 295 | func (iClient *Client) applynsx-smCRDs(ctx context.Context, delete bool) error { 296 | crdYAMLs, err := iClient.getCRDsYAML() 297 | if err != nil { 298 | return err 299 | } 300 | logrus.Debug("processing crds. . .") 301 | for _, crdYAML := range crdYAMLs { 302 | if err := iClient.applyConfigChange(ctx, crdYAML, "", delete, false); err != nil { 303 | return err 304 | } 305 | } 306 | return nil 307 | } 308 | 309 | func (iClient *Client) labelNamespaceForAutoInjection(ctx context.Context, namespace string) error { 310 | ns := &unstructured.Unstructured{} 311 | res := schema.GroupVersionResource{ 312 | Version: "v1", 313 | Resource: "namespaces", 314 | } 315 | ns.SetName(namespace) 316 | ns, err := iClient.getResource(ctx, res, ns) 317 | if err != nil { 318 | if strings.HasSuffix(err.Error(), "not found") { 319 | if err = iClient.createNamespace(ctx, namespace); err != nil { 320 | return err 321 | } 322 | 323 | ns := &unstructured.Unstructured{} 324 | ns.SetName(namespace) 325 | ns, err = iClient.getResource(ctx, res, ns) 326 | if err != nil { 327 | return err 328 | } 329 | } else { 330 | return err 331 | } 332 | } 333 | logrus.Debugf("retrieved namespace: %+#v", ns) 334 | if ns == nil { 335 | ns = &unstructured.Unstructured{} 336 | ns.SetName(namespace) 337 | } 338 | ns.SetLabels(map[string]string{ 339 | "nsx-sm-injection": "enabled", 340 | }) 341 | err = iClient.updateResource(ctx, res, ns) 342 | if err != nil { 343 | return err 344 | } 345 | return nil 346 | } 347 | 348 | func (iClient *Client) createNamespace(ctx context.Context, namespace string) error { 349 | logrus.Debugf("creating namespace: %s", namespace) 350 | yamlFileContents, err := iClient.executeTemplate(ctx, "", namespace, "namespace.yml") 351 | if err != nil { 352 | return err 353 | } 354 | if err := iClient.applyConfigChange(ctx, yamlFileContents, namespace, false, false); err != nil { 355 | return err 356 | } 357 | return nil 358 | } 359 | 360 | func (iClient *Client) executeTemplate(ctx context.Context, username, namespace, templateName string) (string, error) { 361 | tmpl, err := template.ParseFiles(path.Join("nsx-sm", "config_templates", templateName)) 362 | if err != nil { 363 | err = errors.Wrapf(err, "unable to parse template") 364 | logrus.Error(err) 365 | return "", err 366 | } 367 | buf := bytes.NewBufferString("") 368 | err = tmpl.Execute(buf, map[string]string{ 369 | "user_name": username, 370 | "namespace": namespace, 371 | }) 372 | if err != nil { 373 | err = errors.Wrapf(err, "unable to execute template") 374 | logrus.Error(err) 375 | return "", err 376 | } 377 | return buf.String(), nil 378 | } 379 | 380 | func (iClient *Client) executeInstall(ctx context.Context, installmTLS bool, arReq *meshes.ApplyRuleRequest) error { 381 | arReq.Namespace = "" 382 | if arReq.DeleteOp { 383 | defer iClient.applynsx-smCRDs(ctx, arReq.DeleteOp) 384 | } else { 385 | if err := iClient.applynsx-smCRDs(ctx, arReq.DeleteOp); err != nil { 386 | return err 387 | } 388 | } 389 | yamlFileContents, err := iClient.getLatestnsx-smYAML(installmTLS) 390 | if err != nil { 391 | return err 392 | } 393 | if err := iClient.applyConfigChange(ctx, yamlFileContents, arReq.Namespace, arReq.DeleteOp, false); err != nil { 394 | return err 395 | } 396 | return nil 397 | } 398 | 399 | func (iClient *Client) executeBookInfoInstall(ctx context.Context, arReq *meshes.ApplyRuleRequest) error { 400 | if !arReq.DeleteOp { 401 | if err := iClient.labelNamespaceForAutoInjection(ctx, arReq.Namespace); err != nil { 402 | return err 403 | } 404 | } 405 | yamlFileContents, err := iClient.getBookInfoAppYAML() 406 | if err != nil { 407 | return err 408 | } 409 | if err := iClient.applyConfigChange(ctx, yamlFileContents, arReq.Namespace, arReq.DeleteOp, false); err != nil { 410 | return err 411 | } 412 | yamlFileContents, err = iClient.getBookInfoGatewayYAML() 413 | if err != nil { 414 | return err 415 | } 416 | if err := iClient.applyConfigChange(ctx, yamlFileContents, arReq.Namespace, arReq.DeleteOp, false); err != nil { 417 | return err 418 | } 419 | return nil 420 | } 421 | 422 | func (iClient *Client) executeHipsterShopInstall(ctx context.Context, arReq *meshes.ApplyRuleRequest) error { 423 | if !arReq.DeleteOp { 424 | if err := iClient.labelNamespaceForAutoInjection(ctx, arReq.Namespace); err != nil { 425 | return err 426 | } 427 | } 428 | hipsterShopFilecontents := func(fileURL string) (string, error) { 429 | resp, err := http.Get(fileURL) 430 | if err != nil { 431 | err = errors.Wrapf(err, "error getting data from %s", fileURL) 432 | logrus.Error(err) 433 | return "", err 434 | } 435 | defer resp.Body.Close() 436 | if resp.StatusCode == 200 { 437 | body, err := ioutil.ReadAll(resp.Body) 438 | if err != nil { 439 | err = errors.Wrapf(err, "error parsing response from %s", fileURL) 440 | logrus.Error(err) 441 | return "", err 442 | } 443 | return string(body), nil 444 | } 445 | err = errors.Wrapf(err, "Call failed with response status: %s", resp.Status) 446 | logrus.Error(err) 447 | return "", err 448 | } 449 | 450 | kubernetesManifestsContent, err := hipsterShopFilecontents(hipsterShopKubernetesManifestsURL) 451 | if err != nil { 452 | return err 453 | } 454 | nsx-smManifestsContent, err := hipsterShopFilecontents(hipsterShopnsx-smManifestsURL) 455 | if err != nil { 456 | return err 457 | } 458 | 459 | var yamlFileContents = fmt.Sprintf("%s\n---\n%s", kubernetesManifestsContent, nsx-smManifestsContent) 460 | 461 | if err := iClient.applyConfigChange(ctx, yamlFileContents, arReq.Namespace, arReq.DeleteOp, false); err != nil { 462 | return err 463 | } 464 | 465 | return nil 466 | } 467 | 468 | // ApplyOperation is a method invoked to apply a particular operation on the mesh in a namespace 469 | func (iClient *Client) ApplyOperation(ctx context.Context, arReq *meshes.ApplyRuleRequest) (*meshes.ApplyRuleResponse, error) { 470 | if arReq == nil { 471 | return nil, errors.New("mesh client has not been created") 472 | } 473 | 474 | op, ok := supportedOps[arReq.OpName] 475 | if !ok { 476 | return nil, fmt.Errorf("operation id: %s, error: %s is not a valid operation name", arReq.OperationId, arReq.OpName) 477 | } 478 | 479 | if arReq.OpName == customOpCommand && arReq.CustomBody == "" { 480 | return nil, fmt.Errorf("operation id: %s, error: yaml body is empty for %s operation", arReq.OperationId, arReq.OpName) 481 | } 482 | 483 | var yamlFileContents string 484 | var err error 485 | installWithmTLS := false 486 | isCustomOp := false 487 | 488 | switch arReq.OpName { 489 | case installmTLSnsx-smCommand: 490 | installWithmTLS = true 491 | fallthrough 492 | case installnsx-smCommand: 493 | go func() { 494 | opName1 := "deploying" 495 | if arReq.DeleteOp { 496 | opName1 = "removing" 497 | } 498 | if err := iClient.executeInstall(ctx, installWithmTLS, arReq); err != nil { 499 | iClient.eventChan <- &meshes.EventsResponse{ 500 | OperationId: arReq.OperationId, 501 | EventType: meshes.EventType_ERROR, 502 | Summary: fmt.Sprintf("Error while %s nsx-sm", opName1), 503 | Details: err.Error(), 504 | } 505 | return 506 | } 507 | opName := "deployed" 508 | if arReq.DeleteOp { 509 | opName = "removed" 510 | } 511 | iClient.eventChan <- &meshes.EventsResponse{ 512 | OperationId: arReq.OperationId, 513 | EventType: meshes.EventType_INFO, 514 | Summary: fmt.Sprintf("nsx-sm %s successfully", opName), 515 | Details: fmt.Sprintf("The latest version of nsx-sm is now %s.", opName), 516 | } 517 | return 518 | }() 519 | return &meshes.ApplyRuleResponse{ 520 | OperationId: arReq.OperationId, 521 | }, nil 522 | case googleMSSampleApplication: 523 | go func() { 524 | opName1 := "deploying" 525 | if arReq.DeleteOp { 526 | opName1 = "removing" 527 | } 528 | if err := iClient.executeHipsterShopInstall(ctx, arReq); err != nil { 529 | iClient.eventChan <- &meshes.EventsResponse{ 530 | OperationId: arReq.OperationId, 531 | EventType: meshes.EventType_ERROR, 532 | Summary: fmt.Sprintf("Error while %s the Hipster Shop application", opName1), 533 | Details: err.Error(), 534 | } 535 | return 536 | } 537 | opName := "deployed" 538 | if arReq.DeleteOp { 539 | opName = "removed" 540 | } 541 | iClient.eventChan <- &meshes.EventsResponse{ 542 | OperationId: arReq.OperationId, 543 | EventType: meshes.EventType_INFO, 544 | Summary: fmt.Sprintf("The Hipster Shop application %s successfully", opName), 545 | Details: fmt.Sprintf("The Hipster Shop is now %s.", opName), 546 | } 547 | return 548 | }() 549 | return &meshes.ApplyRuleResponse{ 550 | OperationId: arReq.OperationId, 551 | }, nil 552 | 553 | case installBookInfoCommand: 554 | go func() { 555 | opName1 := "deploying" 556 | if arReq.DeleteOp { 557 | opName1 = "removing" 558 | } 559 | if err := iClient.executeBookInfoInstall(ctx, arReq); err != nil { 560 | iClient.eventChan <- &meshes.EventsResponse{ 561 | OperationId: arReq.OperationId, 562 | EventType: meshes.EventType_ERROR, 563 | Summary: fmt.Sprintf("Error while %s the canonical Book Info App", opName1), 564 | Details: err.Error(), 565 | } 566 | return 567 | } 568 | opName := "deployed" 569 | if arReq.DeleteOp { 570 | opName = "removed" 571 | } 572 | iClient.eventChan <- &meshes.EventsResponse{ 573 | OperationId: arReq.OperationId, 574 | EventType: meshes.EventType_INFO, 575 | Summary: fmt.Sprintf("Book Info app %s successfully", opName), 576 | Details: fmt.Sprintf("The nsx-sm canonical Book Info app is now %s.", opName), 577 | } 578 | return 579 | }() 580 | return &meshes.ApplyRuleResponse{ 581 | OperationId: arReq.OperationId, 582 | }, nil 583 | case bookInfoDefaultDestinationRules: 584 | yamlFileContents, err = iClient.getBookInfoDefaultDesinationRulesYAML() 585 | if err != nil { 586 | return nil, err 587 | } 588 | case bookInfoRouteToV1AllServices: 589 | yamlFileContents, err = iClient.getBookInfoRouteToV1AllServicesYAML() 590 | if err != nil { 591 | return nil, err 592 | } 593 | case bookInfoRouteToReviewsV2ForJason: 594 | yamlFileContents, err = iClient.getBookInfoRouteToReviewsV2ForJasonFile() 595 | if err != nil { 596 | return nil, err 597 | } 598 | case bookInfoCanary50pcReviewsV3: 599 | yamlFileContents, err = iClient.getBookInfoCanary50pcReviewsV3File() 600 | if err != nil { 601 | return nil, err 602 | } 603 | case bookInfoCanary100pcReviewsV3: 604 | yamlFileContents, err = iClient.getBookInfoCanary100pcReviewsV3File() 605 | if err != nil { 606 | return nil, err 607 | } 608 | case bookInfoInjectDelayForRatingsForJason: 609 | yamlFileContents, err = iClient.getBookInfoInjectDelayForRatingsForJasonFile() 610 | if err != nil { 611 | return nil, err 612 | } 613 | case bookInfoInjectHTTPAbortToRatingsForJason: 614 | yamlFileContents, err = iClient.getBookInfoInjectHTTPAbortToRatingsForJasonFile() 615 | if err != nil { 616 | return nil, err 617 | } 618 | case installSMI: 619 | if !arReq.DeleteOp && arReq.Namespace != "default" { 620 | iClient.createNamespace(ctx, arReq.Namespace) 621 | } 622 | yamlFileContents, err = getSMIYamls() 623 | if err != nil { 624 | return nil, err 625 | } 626 | case runVet: 627 | go iClient.runVet() 628 | return &meshes.ApplyRuleResponse{ 629 | OperationId: arReq.OperationId, 630 | }, nil 631 | case customOpCommand: 632 | yamlFileContents = arReq.CustomBody 633 | isCustomOp = true 634 | default: 635 | if !arReq.DeleteOp { 636 | if err := iClient.labelNamespaceForAutoInjection(ctx, arReq.Namespace); err != nil { 637 | return nil, err 638 | } 639 | } 640 | yamlFileContents, err = iClient.executeTemplate(ctx, arReq.Username, arReq.Namespace, op.templateName) 641 | if err != nil { 642 | return nil, err 643 | } 644 | } 645 | 646 | go func() { 647 | logrus.Debug("in the routine. . . .") 648 | opName1 := "deploying" 649 | if arReq.DeleteOp { 650 | opName1 = "removing" 651 | } 652 | if err := iClient.applyConfigChange(ctx, yamlFileContents, arReq.Namespace, arReq.DeleteOp, isCustomOp); err != nil { 653 | iClient.eventChan <- &meshes.EventsResponse{ 654 | OperationId: arReq.OperationId, 655 | EventType: meshes.EventType_ERROR, 656 | Summary: fmt.Sprintf("Error while %s \"%s\"", opName1, op.name), 657 | Details: err.Error(), 658 | } 659 | return 660 | } 661 | opName := "deployed" 662 | if arReq.DeleteOp { 663 | opName = "removed" 664 | } 665 | iClient.eventChan <- &meshes.EventsResponse{ 666 | OperationId: arReq.OperationId, 667 | EventType: meshes.EventType_INFO, 668 | Summary: fmt.Sprintf("\"%s\" %s successfully", op.name, opName), 669 | Details: fmt.Sprintf("\"%s\" %s successfully", op.name, opName), 670 | } 671 | }() 672 | 673 | return &meshes.ApplyRuleResponse{ 674 | OperationId: arReq.OperationId, 675 | }, nil 676 | } 677 | 678 | func (iClient *Client) applyConfigChange(ctx context.Context, yamlFileContents, namespace string, delete, isCustomOp bool) error { 679 | // yamls := strings.Split(yamlFileContents, "---") 680 | yamls, err := iClient.splitYAML(yamlFileContents) 681 | if err != nil { 682 | err = errors.Wrap(err, "error while splitting yaml") 683 | logrus.Error(err) 684 | return err 685 | } 686 | for _, yml := range yamls { 687 | if strings.TrimSpace(yml) != "" { 688 | if err := iClient.applyRulePayload(ctx, namespace, []byte(yml), delete, isCustomOp); err != nil { 689 | errStr := strings.TrimSpace(err.Error()) 690 | if delete { 691 | if strings.HasSuffix(errStr, "not found") || 692 | strings.HasSuffix(errStr, "the server could not find the requested resource") { 693 | // logrus.Debugf("skipping error. . .") 694 | continue 695 | } 696 | } else { 697 | if strings.HasSuffix(errStr, "already exists") { 698 | continue 699 | } 700 | } 701 | // logrus.Debugf("returning error: %v", err) 702 | return err 703 | } 704 | } 705 | } 706 | return nil 707 | } 708 | 709 | // SupportedOperations - returns a list of supported operations on the mesh 710 | func (iClient *Client) SupportedOperations(context.Context, *meshes.SupportedOperationsRequest) (*meshes.SupportedOperationsResponse, error) { 711 | supportedOpsCount := len(supportedOps) 712 | result := make([]*meshes.SupportedOperation, supportedOpsCount) 713 | i := 0 714 | for k, sp := range supportedOps { 715 | result[i] = &meshes.SupportedOperation{ 716 | Key: k, 717 | Value: sp.name, 718 | Category: sp.opType, 719 | } 720 | i++ 721 | } 722 | return &meshes.SupportedOperationsResponse{ 723 | Ops: result, 724 | }, nil 725 | } 726 | 727 | // StreamEvents - streams generated/collected events to the client 728 | func (iClient *Client) StreamEvents(in *meshes.EventsRequest, stream meshes.MeshService_StreamEventsServer) error { 729 | logrus.Debugf("waiting on event stream. . .") 730 | for { 731 | select { 732 | case event := <-iClient.eventChan: 733 | logrus.Debugf("sending event: %+#v", event) 734 | if err := stream.Send(event); err != nil { 735 | err = errors.Wrapf(err, "unable to send event") 736 | 737 | // to prevent loosing the event, will re-add to the channel 738 | go func() { 739 | iClient.eventChan <- event 740 | }() 741 | logrus.Error(err) 742 | return err 743 | } 744 | default: 745 | } 746 | time.Sleep(500 * time.Millisecond) 747 | } 748 | return nil 749 | } 750 | 751 | func (iClient *Client) splitYAML(yamlContents string) ([]string, error) { 752 | yamlDecoder, ok := NewDocumentDecoder(ioutil.NopCloser(bytes.NewReader([]byte(yamlContents)))).(*YAMLDecoder) 753 | if !ok { 754 | err := fmt.Errorf("unable to create a yaml decoder") 755 | logrus.Error(err) 756 | return nil, err 757 | } 758 | defer yamlDecoder.Close() 759 | var err error 760 | n := 0 761 | data := [][]byte{} 762 | ind := 0 763 | for err == io.ErrShortBuffer || err == nil { 764 | // for { 765 | d := make([]byte, 1000) 766 | n, err = yamlDecoder.Read(d) 767 | // logrus.Debugf("Read this: %s, count: %d, err: %v", d, n, err) 768 | if len(data) == 0 || len(data) <= ind { 769 | data = append(data, []byte{}) 770 | } 771 | if n > 0 { 772 | data[ind] = append(data[ind], d...) 773 | } 774 | if err == nil { 775 | logrus.Debugf("..............BOUNDARY................") 776 | ind++ 777 | } 778 | } 779 | result := make([]string, len(data)) 780 | for i, row := range data { 781 | r := string(row) 782 | r = strings.Trim(r, "\x00") 783 | logrus.Debugf("ind: %d, data: %s", i, r) 784 | result[i] = r 785 | } 786 | return result, nil 787 | } 788 | -------------------------------------------------------------------------------- /meshes/meshops.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: meshops.proto 3 | 4 | package meshes 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | import ( 11 | context "golang.org/x/net/context" 12 | grpc "google.golang.org/grpc" 13 | ) 14 | 15 | // Reference imports to suppress errors if they are not otherwise used. 16 | var _ = proto.Marshal 17 | var _ = fmt.Errorf 18 | var _ = math.Inf 19 | 20 | // This is a compile-time assertion to ensure that this generated file 21 | // is compatible with the proto package it is being compiled against. 22 | // A compilation error at this line likely means your copy of the 23 | // proto package needs to be updated. 24 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 25 | 26 | type OpCategory int32 27 | 28 | const ( 29 | OpCategory_INSTALL OpCategory = 0 30 | OpCategory_SAMPLE_APPLICATION OpCategory = 1 31 | OpCategory_CONFIGURE OpCategory = 2 32 | OpCategory_VALIDATE OpCategory = 3 33 | OpCategory_CUSTOM OpCategory = 4 34 | ) 35 | 36 | var OpCategory_name = map[int32]string{ 37 | 0: "INSTALL", 38 | 1: "SAMPLE_APPLICATION", 39 | 2: "CONFIGURE", 40 | 3: "VALIDATE", 41 | 4: "CUSTOM", 42 | } 43 | var OpCategory_value = map[string]int32{ 44 | "INSTALL": 0, 45 | "SAMPLE_APPLICATION": 1, 46 | "CONFIGURE": 2, 47 | "VALIDATE": 3, 48 | "CUSTOM": 4, 49 | } 50 | 51 | func (x OpCategory) String() string { 52 | return proto.EnumName(OpCategory_name, int32(x)) 53 | } 54 | func (OpCategory) EnumDescriptor() ([]byte, []int) { 55 | return fileDescriptor_meshops_70742207f69c0a34, []int{0} 56 | } 57 | 58 | type EventType int32 59 | 60 | const ( 61 | EventType_INFO EventType = 0 62 | EventType_WARN EventType = 1 63 | EventType_ERROR EventType = 2 64 | ) 65 | 66 | var EventType_name = map[int32]string{ 67 | 0: "INFO", 68 | 1: "WARN", 69 | 2: "ERROR", 70 | } 71 | var EventType_value = map[string]int32{ 72 | "INFO": 0, 73 | "WARN": 1, 74 | "ERROR": 2, 75 | } 76 | 77 | func (x EventType) String() string { 78 | return proto.EnumName(EventType_name, int32(x)) 79 | } 80 | func (EventType) EnumDescriptor() ([]byte, []int) { 81 | return fileDescriptor_meshops_70742207f69c0a34, []int{1} 82 | } 83 | 84 | type CreateMeshInstanceRequest struct { 85 | K8SConfig []byte `protobuf:"bytes,1,opt,name=k8sConfig,proto3" json:"k8sConfig,omitempty"` 86 | ContextName string `protobuf:"bytes,2,opt,name=contextName,proto3" json:"contextName,omitempty"` 87 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 88 | XXX_unrecognized []byte `json:"-"` 89 | XXX_sizecache int32 `json:"-"` 90 | } 91 | 92 | func (m *CreateMeshInstanceRequest) Reset() { *m = CreateMeshInstanceRequest{} } 93 | func (m *CreateMeshInstanceRequest) String() string { return proto.CompactTextString(m) } 94 | func (*CreateMeshInstanceRequest) ProtoMessage() {} 95 | func (*CreateMeshInstanceRequest) Descriptor() ([]byte, []int) { 96 | return fileDescriptor_meshops_70742207f69c0a34, []int{0} 97 | } 98 | func (m *CreateMeshInstanceRequest) XXX_Unmarshal(b []byte) error { 99 | return xxx_messageInfo_CreateMeshInstanceRequest.Unmarshal(m, b) 100 | } 101 | func (m *CreateMeshInstanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 102 | return xxx_messageInfo_CreateMeshInstanceRequest.Marshal(b, m, deterministic) 103 | } 104 | func (dst *CreateMeshInstanceRequest) XXX_Merge(src proto.Message) { 105 | xxx_messageInfo_CreateMeshInstanceRequest.Merge(dst, src) 106 | } 107 | func (m *CreateMeshInstanceRequest) XXX_Size() int { 108 | return xxx_messageInfo_CreateMeshInstanceRequest.Size(m) 109 | } 110 | func (m *CreateMeshInstanceRequest) XXX_DiscardUnknown() { 111 | xxx_messageInfo_CreateMeshInstanceRequest.DiscardUnknown(m) 112 | } 113 | 114 | var xxx_messageInfo_CreateMeshInstanceRequest proto.InternalMessageInfo 115 | 116 | func (m *CreateMeshInstanceRequest) GetK8SConfig() []byte { 117 | if m != nil { 118 | return m.K8SConfig 119 | } 120 | return nil 121 | } 122 | 123 | func (m *CreateMeshInstanceRequest) GetContextName() string { 124 | if m != nil { 125 | return m.ContextName 126 | } 127 | return "" 128 | } 129 | 130 | type CreateMeshInstanceResponse struct { 131 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 132 | XXX_unrecognized []byte `json:"-"` 133 | XXX_sizecache int32 `json:"-"` 134 | } 135 | 136 | func (m *CreateMeshInstanceResponse) Reset() { *m = CreateMeshInstanceResponse{} } 137 | func (m *CreateMeshInstanceResponse) String() string { return proto.CompactTextString(m) } 138 | func (*CreateMeshInstanceResponse) ProtoMessage() {} 139 | func (*CreateMeshInstanceResponse) Descriptor() ([]byte, []int) { 140 | return fileDescriptor_meshops_70742207f69c0a34, []int{1} 141 | } 142 | func (m *CreateMeshInstanceResponse) XXX_Unmarshal(b []byte) error { 143 | return xxx_messageInfo_CreateMeshInstanceResponse.Unmarshal(m, b) 144 | } 145 | func (m *CreateMeshInstanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 146 | return xxx_messageInfo_CreateMeshInstanceResponse.Marshal(b, m, deterministic) 147 | } 148 | func (dst *CreateMeshInstanceResponse) XXX_Merge(src proto.Message) { 149 | xxx_messageInfo_CreateMeshInstanceResponse.Merge(dst, src) 150 | } 151 | func (m *CreateMeshInstanceResponse) XXX_Size() int { 152 | return xxx_messageInfo_CreateMeshInstanceResponse.Size(m) 153 | } 154 | func (m *CreateMeshInstanceResponse) XXX_DiscardUnknown() { 155 | xxx_messageInfo_CreateMeshInstanceResponse.DiscardUnknown(m) 156 | } 157 | 158 | var xxx_messageInfo_CreateMeshInstanceResponse proto.InternalMessageInfo 159 | 160 | type MeshNameRequest struct { 161 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 162 | XXX_unrecognized []byte `json:"-"` 163 | XXX_sizecache int32 `json:"-"` 164 | } 165 | 166 | func (m *MeshNameRequest) Reset() { *m = MeshNameRequest{} } 167 | func (m *MeshNameRequest) String() string { return proto.CompactTextString(m) } 168 | func (*MeshNameRequest) ProtoMessage() {} 169 | func (*MeshNameRequest) Descriptor() ([]byte, []int) { 170 | return fileDescriptor_meshops_70742207f69c0a34, []int{2} 171 | } 172 | func (m *MeshNameRequest) XXX_Unmarshal(b []byte) error { 173 | return xxx_messageInfo_MeshNameRequest.Unmarshal(m, b) 174 | } 175 | func (m *MeshNameRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 176 | return xxx_messageInfo_MeshNameRequest.Marshal(b, m, deterministic) 177 | } 178 | func (dst *MeshNameRequest) XXX_Merge(src proto.Message) { 179 | xxx_messageInfo_MeshNameRequest.Merge(dst, src) 180 | } 181 | func (m *MeshNameRequest) XXX_Size() int { 182 | return xxx_messageInfo_MeshNameRequest.Size(m) 183 | } 184 | func (m *MeshNameRequest) XXX_DiscardUnknown() { 185 | xxx_messageInfo_MeshNameRequest.DiscardUnknown(m) 186 | } 187 | 188 | var xxx_messageInfo_MeshNameRequest proto.InternalMessageInfo 189 | 190 | type MeshNameResponse struct { 191 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 192 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 193 | XXX_unrecognized []byte `json:"-"` 194 | XXX_sizecache int32 `json:"-"` 195 | } 196 | 197 | func (m *MeshNameResponse) Reset() { *m = MeshNameResponse{} } 198 | func (m *MeshNameResponse) String() string { return proto.CompactTextString(m) } 199 | func (*MeshNameResponse) ProtoMessage() {} 200 | func (*MeshNameResponse) Descriptor() ([]byte, []int) { 201 | return fileDescriptor_meshops_70742207f69c0a34, []int{3} 202 | } 203 | func (m *MeshNameResponse) XXX_Unmarshal(b []byte) error { 204 | return xxx_messageInfo_MeshNameResponse.Unmarshal(m, b) 205 | } 206 | func (m *MeshNameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 207 | return xxx_messageInfo_MeshNameResponse.Marshal(b, m, deterministic) 208 | } 209 | func (dst *MeshNameResponse) XXX_Merge(src proto.Message) { 210 | xxx_messageInfo_MeshNameResponse.Merge(dst, src) 211 | } 212 | func (m *MeshNameResponse) XXX_Size() int { 213 | return xxx_messageInfo_MeshNameResponse.Size(m) 214 | } 215 | func (m *MeshNameResponse) XXX_DiscardUnknown() { 216 | xxx_messageInfo_MeshNameResponse.DiscardUnknown(m) 217 | } 218 | 219 | var xxx_messageInfo_MeshNameResponse proto.InternalMessageInfo 220 | 221 | func (m *MeshNameResponse) GetName() string { 222 | if m != nil { 223 | return m.Name 224 | } 225 | return "" 226 | } 227 | 228 | type ApplyRuleRequest struct { 229 | OpName string `protobuf:"bytes,1,opt,name=opName,proto3" json:"opName,omitempty"` 230 | Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` 231 | Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` 232 | CustomBody string `protobuf:"bytes,4,opt,name=custom_body,json=customBody,proto3" json:"custom_body,omitempty"` 233 | DeleteOp bool `protobuf:"varint,5,opt,name=delete_op,json=deleteOp,proto3" json:"delete_op,omitempty"` 234 | OperationId string `protobuf:"bytes,6,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` 235 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 236 | XXX_unrecognized []byte `json:"-"` 237 | XXX_sizecache int32 `json:"-"` 238 | } 239 | 240 | func (m *ApplyRuleRequest) Reset() { *m = ApplyRuleRequest{} } 241 | func (m *ApplyRuleRequest) String() string { return proto.CompactTextString(m) } 242 | func (*ApplyRuleRequest) ProtoMessage() {} 243 | func (*ApplyRuleRequest) Descriptor() ([]byte, []int) { 244 | return fileDescriptor_meshops_70742207f69c0a34, []int{4} 245 | } 246 | func (m *ApplyRuleRequest) XXX_Unmarshal(b []byte) error { 247 | return xxx_messageInfo_ApplyRuleRequest.Unmarshal(m, b) 248 | } 249 | func (m *ApplyRuleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 250 | return xxx_messageInfo_ApplyRuleRequest.Marshal(b, m, deterministic) 251 | } 252 | func (dst *ApplyRuleRequest) XXX_Merge(src proto.Message) { 253 | xxx_messageInfo_ApplyRuleRequest.Merge(dst, src) 254 | } 255 | func (m *ApplyRuleRequest) XXX_Size() int { 256 | return xxx_messageInfo_ApplyRuleRequest.Size(m) 257 | } 258 | func (m *ApplyRuleRequest) XXX_DiscardUnknown() { 259 | xxx_messageInfo_ApplyRuleRequest.DiscardUnknown(m) 260 | } 261 | 262 | var xxx_messageInfo_ApplyRuleRequest proto.InternalMessageInfo 263 | 264 | func (m *ApplyRuleRequest) GetOpName() string { 265 | if m != nil { 266 | return m.OpName 267 | } 268 | return "" 269 | } 270 | 271 | func (m *ApplyRuleRequest) GetNamespace() string { 272 | if m != nil { 273 | return m.Namespace 274 | } 275 | return "" 276 | } 277 | 278 | func (m *ApplyRuleRequest) GetUsername() string { 279 | if m != nil { 280 | return m.Username 281 | } 282 | return "" 283 | } 284 | 285 | func (m *ApplyRuleRequest) GetCustomBody() string { 286 | if m != nil { 287 | return m.CustomBody 288 | } 289 | return "" 290 | } 291 | 292 | func (m *ApplyRuleRequest) GetDeleteOp() bool { 293 | if m != nil { 294 | return m.DeleteOp 295 | } 296 | return false 297 | } 298 | 299 | func (m *ApplyRuleRequest) GetOperationId() string { 300 | if m != nil { 301 | return m.OperationId 302 | } 303 | return "" 304 | } 305 | 306 | type ApplyRuleResponse struct { 307 | Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` 308 | OperationId string `protobuf:"bytes,2,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` 309 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 310 | XXX_unrecognized []byte `json:"-"` 311 | XXX_sizecache int32 `json:"-"` 312 | } 313 | 314 | func (m *ApplyRuleResponse) Reset() { *m = ApplyRuleResponse{} } 315 | func (m *ApplyRuleResponse) String() string { return proto.CompactTextString(m) } 316 | func (*ApplyRuleResponse) ProtoMessage() {} 317 | func (*ApplyRuleResponse) Descriptor() ([]byte, []int) { 318 | return fileDescriptor_meshops_70742207f69c0a34, []int{5} 319 | } 320 | func (m *ApplyRuleResponse) XXX_Unmarshal(b []byte) error { 321 | return xxx_messageInfo_ApplyRuleResponse.Unmarshal(m, b) 322 | } 323 | func (m *ApplyRuleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 324 | return xxx_messageInfo_ApplyRuleResponse.Marshal(b, m, deterministic) 325 | } 326 | func (dst *ApplyRuleResponse) XXX_Merge(src proto.Message) { 327 | xxx_messageInfo_ApplyRuleResponse.Merge(dst, src) 328 | } 329 | func (m *ApplyRuleResponse) XXX_Size() int { 330 | return xxx_messageInfo_ApplyRuleResponse.Size(m) 331 | } 332 | func (m *ApplyRuleResponse) XXX_DiscardUnknown() { 333 | xxx_messageInfo_ApplyRuleResponse.DiscardUnknown(m) 334 | } 335 | 336 | var xxx_messageInfo_ApplyRuleResponse proto.InternalMessageInfo 337 | 338 | func (m *ApplyRuleResponse) GetError() string { 339 | if m != nil { 340 | return m.Error 341 | } 342 | return "" 343 | } 344 | 345 | func (m *ApplyRuleResponse) GetOperationId() string { 346 | if m != nil { 347 | return m.OperationId 348 | } 349 | return "" 350 | } 351 | 352 | type SupportedOperationsRequest struct { 353 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 354 | XXX_unrecognized []byte `json:"-"` 355 | XXX_sizecache int32 `json:"-"` 356 | } 357 | 358 | func (m *SupportedOperationsRequest) Reset() { *m = SupportedOperationsRequest{} } 359 | func (m *SupportedOperationsRequest) String() string { return proto.CompactTextString(m) } 360 | func (*SupportedOperationsRequest) ProtoMessage() {} 361 | func (*SupportedOperationsRequest) Descriptor() ([]byte, []int) { 362 | return fileDescriptor_meshops_70742207f69c0a34, []int{6} 363 | } 364 | func (m *SupportedOperationsRequest) XXX_Unmarshal(b []byte) error { 365 | return xxx_messageInfo_SupportedOperationsRequest.Unmarshal(m, b) 366 | } 367 | func (m *SupportedOperationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 368 | return xxx_messageInfo_SupportedOperationsRequest.Marshal(b, m, deterministic) 369 | } 370 | func (dst *SupportedOperationsRequest) XXX_Merge(src proto.Message) { 371 | xxx_messageInfo_SupportedOperationsRequest.Merge(dst, src) 372 | } 373 | func (m *SupportedOperationsRequest) XXX_Size() int { 374 | return xxx_messageInfo_SupportedOperationsRequest.Size(m) 375 | } 376 | func (m *SupportedOperationsRequest) XXX_DiscardUnknown() { 377 | xxx_messageInfo_SupportedOperationsRequest.DiscardUnknown(m) 378 | } 379 | 380 | var xxx_messageInfo_SupportedOperationsRequest proto.InternalMessageInfo 381 | 382 | type SupportedOperationsResponse struct { 383 | Ops []*SupportedOperation `protobuf:"bytes,1,rep,name=ops,proto3" json:"ops,omitempty"` 384 | Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` 385 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 386 | XXX_unrecognized []byte `json:"-"` 387 | XXX_sizecache int32 `json:"-"` 388 | } 389 | 390 | func (m *SupportedOperationsResponse) Reset() { *m = SupportedOperationsResponse{} } 391 | func (m *SupportedOperationsResponse) String() string { return proto.CompactTextString(m) } 392 | func (*SupportedOperationsResponse) ProtoMessage() {} 393 | func (*SupportedOperationsResponse) Descriptor() ([]byte, []int) { 394 | return fileDescriptor_meshops_70742207f69c0a34, []int{7} 395 | } 396 | func (m *SupportedOperationsResponse) XXX_Unmarshal(b []byte) error { 397 | return xxx_messageInfo_SupportedOperationsResponse.Unmarshal(m, b) 398 | } 399 | func (m *SupportedOperationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 400 | return xxx_messageInfo_SupportedOperationsResponse.Marshal(b, m, deterministic) 401 | } 402 | func (dst *SupportedOperationsResponse) XXX_Merge(src proto.Message) { 403 | xxx_messageInfo_SupportedOperationsResponse.Merge(dst, src) 404 | } 405 | func (m *SupportedOperationsResponse) XXX_Size() int { 406 | return xxx_messageInfo_SupportedOperationsResponse.Size(m) 407 | } 408 | func (m *SupportedOperationsResponse) XXX_DiscardUnknown() { 409 | xxx_messageInfo_SupportedOperationsResponse.DiscardUnknown(m) 410 | } 411 | 412 | var xxx_messageInfo_SupportedOperationsResponse proto.InternalMessageInfo 413 | 414 | func (m *SupportedOperationsResponse) GetOps() []*SupportedOperation { 415 | if m != nil { 416 | return m.Ops 417 | } 418 | return nil 419 | } 420 | 421 | func (m *SupportedOperationsResponse) GetError() string { 422 | if m != nil { 423 | return m.Error 424 | } 425 | return "" 426 | } 427 | 428 | type SupportedOperation struct { 429 | Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` 430 | Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` 431 | Category OpCategory `protobuf:"varint,3,opt,name=category,proto3,enum=meshes.OpCategory" json:"category,omitempty"` 432 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 433 | XXX_unrecognized []byte `json:"-"` 434 | XXX_sizecache int32 `json:"-"` 435 | } 436 | 437 | func (m *SupportedOperation) Reset() { *m = SupportedOperation{} } 438 | func (m *SupportedOperation) String() string { return proto.CompactTextString(m) } 439 | func (*SupportedOperation) ProtoMessage() {} 440 | func (*SupportedOperation) Descriptor() ([]byte, []int) { 441 | return fileDescriptor_meshops_70742207f69c0a34, []int{8} 442 | } 443 | func (m *SupportedOperation) XXX_Unmarshal(b []byte) error { 444 | return xxx_messageInfo_SupportedOperation.Unmarshal(m, b) 445 | } 446 | func (m *SupportedOperation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 447 | return xxx_messageInfo_SupportedOperation.Marshal(b, m, deterministic) 448 | } 449 | func (dst *SupportedOperation) XXX_Merge(src proto.Message) { 450 | xxx_messageInfo_SupportedOperation.Merge(dst, src) 451 | } 452 | func (m *SupportedOperation) XXX_Size() int { 453 | return xxx_messageInfo_SupportedOperation.Size(m) 454 | } 455 | func (m *SupportedOperation) XXX_DiscardUnknown() { 456 | xxx_messageInfo_SupportedOperation.DiscardUnknown(m) 457 | } 458 | 459 | var xxx_messageInfo_SupportedOperation proto.InternalMessageInfo 460 | 461 | func (m *SupportedOperation) GetKey() string { 462 | if m != nil { 463 | return m.Key 464 | } 465 | return "" 466 | } 467 | 468 | func (m *SupportedOperation) GetValue() string { 469 | if m != nil { 470 | return m.Value 471 | } 472 | return "" 473 | } 474 | 475 | func (m *SupportedOperation) GetCategory() OpCategory { 476 | if m != nil { 477 | return m.Category 478 | } 479 | return OpCategory_INSTALL 480 | } 481 | 482 | type EventsRequest struct { 483 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 484 | XXX_unrecognized []byte `json:"-"` 485 | XXX_sizecache int32 `json:"-"` 486 | } 487 | 488 | func (m *EventsRequest) Reset() { *m = EventsRequest{} } 489 | func (m *EventsRequest) String() string { return proto.CompactTextString(m) } 490 | func (*EventsRequest) ProtoMessage() {} 491 | func (*EventsRequest) Descriptor() ([]byte, []int) { 492 | return fileDescriptor_meshops_70742207f69c0a34, []int{9} 493 | } 494 | func (m *EventsRequest) XXX_Unmarshal(b []byte) error { 495 | return xxx_messageInfo_EventsRequest.Unmarshal(m, b) 496 | } 497 | func (m *EventsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 498 | return xxx_messageInfo_EventsRequest.Marshal(b, m, deterministic) 499 | } 500 | func (dst *EventsRequest) XXX_Merge(src proto.Message) { 501 | xxx_messageInfo_EventsRequest.Merge(dst, src) 502 | } 503 | func (m *EventsRequest) XXX_Size() int { 504 | return xxx_messageInfo_EventsRequest.Size(m) 505 | } 506 | func (m *EventsRequest) XXX_DiscardUnknown() { 507 | xxx_messageInfo_EventsRequest.DiscardUnknown(m) 508 | } 509 | 510 | var xxx_messageInfo_EventsRequest proto.InternalMessageInfo 511 | 512 | type EventsResponse struct { 513 | EventType EventType `protobuf:"varint,1,opt,name=event_type,json=eventType,proto3,enum=meshes.EventType" json:"event_type,omitempty"` 514 | Summary string `protobuf:"bytes,2,opt,name=summary,proto3" json:"summary,omitempty"` 515 | Details string `protobuf:"bytes,3,opt,name=details,proto3" json:"details,omitempty"` 516 | OperationId string `protobuf:"bytes,4,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` 517 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 518 | XXX_unrecognized []byte `json:"-"` 519 | XXX_sizecache int32 `json:"-"` 520 | } 521 | 522 | func (m *EventsResponse) Reset() { *m = EventsResponse{} } 523 | func (m *EventsResponse) String() string { return proto.CompactTextString(m) } 524 | func (*EventsResponse) ProtoMessage() {} 525 | func (*EventsResponse) Descriptor() ([]byte, []int) { 526 | return fileDescriptor_meshops_70742207f69c0a34, []int{10} 527 | } 528 | func (m *EventsResponse) XXX_Unmarshal(b []byte) error { 529 | return xxx_messageInfo_EventsResponse.Unmarshal(m, b) 530 | } 531 | func (m *EventsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 532 | return xxx_messageInfo_EventsResponse.Marshal(b, m, deterministic) 533 | } 534 | func (dst *EventsResponse) XXX_Merge(src proto.Message) { 535 | xxx_messageInfo_EventsResponse.Merge(dst, src) 536 | } 537 | func (m *EventsResponse) XXX_Size() int { 538 | return xxx_messageInfo_EventsResponse.Size(m) 539 | } 540 | func (m *EventsResponse) XXX_DiscardUnknown() { 541 | xxx_messageInfo_EventsResponse.DiscardUnknown(m) 542 | } 543 | 544 | var xxx_messageInfo_EventsResponse proto.InternalMessageInfo 545 | 546 | func (m *EventsResponse) GetEventType() EventType { 547 | if m != nil { 548 | return m.EventType 549 | } 550 | return EventType_INFO 551 | } 552 | 553 | func (m *EventsResponse) GetSummary() string { 554 | if m != nil { 555 | return m.Summary 556 | } 557 | return "" 558 | } 559 | 560 | func (m *EventsResponse) GetDetails() string { 561 | if m != nil { 562 | return m.Details 563 | } 564 | return "" 565 | } 566 | 567 | func (m *EventsResponse) GetOperationId() string { 568 | if m != nil { 569 | return m.OperationId 570 | } 571 | return "" 572 | } 573 | 574 | func init() { 575 | proto.RegisterType((*CreateMeshInstanceRequest)(nil), "meshes.CreateMeshInstanceRequest") 576 | proto.RegisterType((*CreateMeshInstanceResponse)(nil), "meshes.CreateMeshInstanceResponse") 577 | proto.RegisterType((*MeshNameRequest)(nil), "meshes.MeshNameRequest") 578 | proto.RegisterType((*MeshNameResponse)(nil), "meshes.MeshNameResponse") 579 | proto.RegisterType((*ApplyRuleRequest)(nil), "meshes.ApplyRuleRequest") 580 | proto.RegisterType((*ApplyRuleResponse)(nil), "meshes.ApplyRuleResponse") 581 | proto.RegisterType((*SupportedOperationsRequest)(nil), "meshes.SupportedOperationsRequest") 582 | proto.RegisterType((*SupportedOperationsResponse)(nil), "meshes.SupportedOperationsResponse") 583 | proto.RegisterType((*SupportedOperation)(nil), "meshes.SupportedOperation") 584 | proto.RegisterType((*EventsRequest)(nil), "meshes.EventsRequest") 585 | proto.RegisterType((*EventsResponse)(nil), "meshes.EventsResponse") 586 | proto.RegisterEnum("meshes.OpCategory", OpCategory_name, OpCategory_value) 587 | proto.RegisterEnum("meshes.EventType", EventType_name, EventType_value) 588 | } 589 | 590 | // Reference imports to suppress errors if they are not otherwise used. 591 | var _ context.Context 592 | var _ grpc.ClientConn 593 | 594 | // This is a compile-time assertion to ensure that this generated file 595 | // is compatible with the grpc package it is being compiled against. 596 | const _ = grpc.SupportPackageIsVersion4 597 | 598 | // MeshServiceClient is the client API for MeshService service. 599 | // 600 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 601 | type MeshServiceClient interface { 602 | CreateMeshInstance(ctx context.Context, in *CreateMeshInstanceRequest, opts ...grpc.CallOption) (*CreateMeshInstanceResponse, error) 603 | MeshName(ctx context.Context, in *MeshNameRequest, opts ...grpc.CallOption) (*MeshNameResponse, error) 604 | ApplyOperation(ctx context.Context, in *ApplyRuleRequest, opts ...grpc.CallOption) (*ApplyRuleResponse, error) 605 | SupportedOperations(ctx context.Context, in *SupportedOperationsRequest, opts ...grpc.CallOption) (*SupportedOperationsResponse, error) 606 | StreamEvents(ctx context.Context, in *EventsRequest, opts ...grpc.CallOption) (MeshService_StreamEventsClient, error) 607 | } 608 | 609 | type meshServiceClient struct { 610 | cc *grpc.ClientConn 611 | } 612 | 613 | func NewMeshServiceClient(cc *grpc.ClientConn) MeshServiceClient { 614 | return &meshServiceClient{cc} 615 | } 616 | 617 | func (c *meshServiceClient) CreateMeshInstance(ctx context.Context, in *CreateMeshInstanceRequest, opts ...grpc.CallOption) (*CreateMeshInstanceResponse, error) { 618 | out := new(CreateMeshInstanceResponse) 619 | err := c.cc.Invoke(ctx, "/meshes.MeshService/CreateMeshInstance", in, out, opts...) 620 | if err != nil { 621 | return nil, err 622 | } 623 | return out, nil 624 | } 625 | 626 | func (c *meshServiceClient) MeshName(ctx context.Context, in *MeshNameRequest, opts ...grpc.CallOption) (*MeshNameResponse, error) { 627 | out := new(MeshNameResponse) 628 | err := c.cc.Invoke(ctx, "/meshes.MeshService/MeshName", in, out, opts...) 629 | if err != nil { 630 | return nil, err 631 | } 632 | return out, nil 633 | } 634 | 635 | func (c *meshServiceClient) ApplyOperation(ctx context.Context, in *ApplyRuleRequest, opts ...grpc.CallOption) (*ApplyRuleResponse, error) { 636 | out := new(ApplyRuleResponse) 637 | err := c.cc.Invoke(ctx, "/meshes.MeshService/ApplyOperation", in, out, opts...) 638 | if err != nil { 639 | return nil, err 640 | } 641 | return out, nil 642 | } 643 | 644 | func (c *meshServiceClient) SupportedOperations(ctx context.Context, in *SupportedOperationsRequest, opts ...grpc.CallOption) (*SupportedOperationsResponse, error) { 645 | out := new(SupportedOperationsResponse) 646 | err := c.cc.Invoke(ctx, "/meshes.MeshService/SupportedOperations", in, out, opts...) 647 | if err != nil { 648 | return nil, err 649 | } 650 | return out, nil 651 | } 652 | 653 | func (c *meshServiceClient) StreamEvents(ctx context.Context, in *EventsRequest, opts ...grpc.CallOption) (MeshService_StreamEventsClient, error) { 654 | stream, err := c.cc.NewStream(ctx, &_MeshService_serviceDesc.Streams[0], "/meshes.MeshService/StreamEvents", opts...) 655 | if err != nil { 656 | return nil, err 657 | } 658 | x := &meshServiceStreamEventsClient{stream} 659 | if err := x.ClientStream.SendMsg(in); err != nil { 660 | return nil, err 661 | } 662 | if err := x.ClientStream.CloseSend(); err != nil { 663 | return nil, err 664 | } 665 | return x, nil 666 | } 667 | 668 | type MeshService_StreamEventsClient interface { 669 | Recv() (*EventsResponse, error) 670 | grpc.ClientStream 671 | } 672 | 673 | type meshServiceStreamEventsClient struct { 674 | grpc.ClientStream 675 | } 676 | 677 | func (x *meshServiceStreamEventsClient) Recv() (*EventsResponse, error) { 678 | m := new(EventsResponse) 679 | if err := x.ClientStream.RecvMsg(m); err != nil { 680 | return nil, err 681 | } 682 | return m, nil 683 | } 684 | 685 | // MeshServiceServer is the server API for MeshService service. 686 | type MeshServiceServer interface { 687 | CreateMeshInstance(context.Context, *CreateMeshInstanceRequest) (*CreateMeshInstanceResponse, error) 688 | MeshName(context.Context, *MeshNameRequest) (*MeshNameResponse, error) 689 | ApplyOperation(context.Context, *ApplyRuleRequest) (*ApplyRuleResponse, error) 690 | SupportedOperations(context.Context, *SupportedOperationsRequest) (*SupportedOperationsResponse, error) 691 | StreamEvents(*EventsRequest, MeshService_StreamEventsServer) error 692 | } 693 | 694 | func RegisterMeshServiceServer(s *grpc.Server, srv MeshServiceServer) { 695 | s.RegisterService(&_MeshService_serviceDesc, srv) 696 | } 697 | 698 | func _MeshService_CreateMeshInstance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 699 | in := new(CreateMeshInstanceRequest) 700 | if err := dec(in); err != nil { 701 | return nil, err 702 | } 703 | if interceptor == nil { 704 | return srv.(MeshServiceServer).CreateMeshInstance(ctx, in) 705 | } 706 | info := &grpc.UnaryServerInfo{ 707 | Server: srv, 708 | FullMethod: "/meshes.MeshService/CreateMeshInstance", 709 | } 710 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 711 | return srv.(MeshServiceServer).CreateMeshInstance(ctx, req.(*CreateMeshInstanceRequest)) 712 | } 713 | return interceptor(ctx, in, info, handler) 714 | } 715 | 716 | func _MeshService_MeshName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 717 | in := new(MeshNameRequest) 718 | if err := dec(in); err != nil { 719 | return nil, err 720 | } 721 | if interceptor == nil { 722 | return srv.(MeshServiceServer).MeshName(ctx, in) 723 | } 724 | info := &grpc.UnaryServerInfo{ 725 | Server: srv, 726 | FullMethod: "/meshes.MeshService/MeshName", 727 | } 728 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 729 | return srv.(MeshServiceServer).MeshName(ctx, req.(*MeshNameRequest)) 730 | } 731 | return interceptor(ctx, in, info, handler) 732 | } 733 | 734 | func _MeshService_ApplyOperation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 735 | in := new(ApplyRuleRequest) 736 | if err := dec(in); err != nil { 737 | return nil, err 738 | } 739 | if interceptor == nil { 740 | return srv.(MeshServiceServer).ApplyOperation(ctx, in) 741 | } 742 | info := &grpc.UnaryServerInfo{ 743 | Server: srv, 744 | FullMethod: "/meshes.MeshService/ApplyOperation", 745 | } 746 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 747 | return srv.(MeshServiceServer).ApplyOperation(ctx, req.(*ApplyRuleRequest)) 748 | } 749 | return interceptor(ctx, in, info, handler) 750 | } 751 | 752 | func _MeshService_SupportedOperations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 753 | in := new(SupportedOperationsRequest) 754 | if err := dec(in); err != nil { 755 | return nil, err 756 | } 757 | if interceptor == nil { 758 | return srv.(MeshServiceServer).SupportedOperations(ctx, in) 759 | } 760 | info := &grpc.UnaryServerInfo{ 761 | Server: srv, 762 | FullMethod: "/meshes.MeshService/SupportedOperations", 763 | } 764 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 765 | return srv.(MeshServiceServer).SupportedOperations(ctx, req.(*SupportedOperationsRequest)) 766 | } 767 | return interceptor(ctx, in, info, handler) 768 | } 769 | 770 | func _MeshService_StreamEvents_Handler(srv interface{}, stream grpc.ServerStream) error { 771 | m := new(EventsRequest) 772 | if err := stream.RecvMsg(m); err != nil { 773 | return err 774 | } 775 | return srv.(MeshServiceServer).StreamEvents(m, &meshServiceStreamEventsServer{stream}) 776 | } 777 | 778 | type MeshService_StreamEventsServer interface { 779 | Send(*EventsResponse) error 780 | grpc.ServerStream 781 | } 782 | 783 | type meshServiceStreamEventsServer struct { 784 | grpc.ServerStream 785 | } 786 | 787 | func (x *meshServiceStreamEventsServer) Send(m *EventsResponse) error { 788 | return x.ServerStream.SendMsg(m) 789 | } 790 | 791 | var _MeshService_serviceDesc = grpc.ServiceDesc{ 792 | ServiceName: "meshes.MeshService", 793 | HandlerType: (*MeshServiceServer)(nil), 794 | Methods: []grpc.MethodDesc{ 795 | { 796 | MethodName: "CreateMeshInstance", 797 | Handler: _MeshService_CreateMeshInstance_Handler, 798 | }, 799 | { 800 | MethodName: "MeshName", 801 | Handler: _MeshService_MeshName_Handler, 802 | }, 803 | { 804 | MethodName: "ApplyOperation", 805 | Handler: _MeshService_ApplyOperation_Handler, 806 | }, 807 | { 808 | MethodName: "SupportedOperations", 809 | Handler: _MeshService_SupportedOperations_Handler, 810 | }, 811 | }, 812 | Streams: []grpc.StreamDesc{ 813 | { 814 | StreamName: "StreamEvents", 815 | Handler: _MeshService_StreamEvents_Handler, 816 | ServerStreams: true, 817 | }, 818 | }, 819 | Metadata: "meshops.proto", 820 | } 821 | 822 | func init() { proto.RegisterFile("meshops.proto", fileDescriptor_meshops_70742207f69c0a34) } 823 | 824 | var fileDescriptor_meshops_70742207f69c0a34 = []byte{ 825 | // 676 bytes of a gzipped FileDescriptorProto 826 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0x61, 0x6f, 0xda, 0x3c, 827 | 0x10, 0x6e, 0x80, 0x52, 0x38, 0x28, 0x4d, 0xfd, 0xbe, 0xeb, 0xd2, 0xb4, 0xd2, 0x68, 0x26, 0x4d, 828 | 0xa8, 0x9a, 0x50, 0xc5, 0xbe, 0xec, 0xdb, 0x94, 0x31, 0x5a, 0x45, 0xa2, 0xa4, 0x0a, 0x74, 0x93, 829 | 0x36, 0x4d, 0x2c, 0x85, 0x5b, 0x8b, 0x0a, 0xb1, 0x17, 0x9b, 0x6a, 0xf9, 0x29, 0xd3, 0x7e, 0xcf, 830 | 0xfe, 0xd7, 0xe4, 0x24, 0x0e, 0x5d, 0x43, 0xfb, 0xcd, 0xf7, 0xdc, 0xf9, 0xf1, 0x3d, 0xf6, 0x73, 831 | 0x86, 0xed, 0x05, 0xf2, 0x1b, 0xca, 0x78, 0x9b, 0x85, 0x54, 0x50, 0x52, 0x96, 0x21, 0x72, 0xeb, 832 | 0x0b, 0xec, 0x77, 0x43, 0xf4, 0x05, 0x9e, 0x23, 0xbf, 0x71, 0x02, 0x2e, 0xfc, 0x60, 0x82, 0x1e, 833 | 0xfe, 0x58, 0x22, 0x17, 0xe4, 0x10, 0xaa, 0xb7, 0x6f, 0x79, 0x97, 0x06, 0xdf, 0x67, 0xd7, 0x86, 834 | 0xd6, 0xd4, 0x5a, 0x75, 0x6f, 0x05, 0x90, 0x26, 0xd4, 0x26, 0x34, 0x10, 0xf8, 0x53, 0x0c, 0xfc, 835 | 0x05, 0x1a, 0x85, 0xa6, 0xd6, 0xaa, 0x7a, 0xf7, 0x21, 0xeb, 0x10, 0xcc, 0x75, 0xe4, 0x9c, 0xd1, 836 | 0x80, 0xa3, 0xb5, 0x0b, 0x3b, 0x12, 0x97, 0x95, 0xe9, 0x81, 0xd6, 0x2b, 0xd0, 0x57, 0x50, 0x52, 837 | 0x46, 0x08, 0x94, 0x02, 0xc9, 0xaf, 0xc5, 0xfc, 0xf1, 0xda, 0xfa, 0xa3, 0x81, 0x6e, 0x33, 0x36, 838 | 0x8f, 0xbc, 0xe5, 0x3c, 0xeb, 0x76, 0x0f, 0xca, 0x94, 0x0d, 0x56, 0xa5, 0x69, 0x24, 0x55, 0xc8, 839 | 0x4d, 0x9c, 0xf9, 0x13, 0xd5, 0xe5, 0x0a, 0x20, 0x26, 0x54, 0x96, 0x1c, 0xc3, 0xf8, 0x88, 0x62, 840 | 0x9c, 0xcc, 0x62, 0xf2, 0x02, 0x6a, 0x93, 0x25, 0x17, 0x74, 0x31, 0xbe, 0xa2, 0xd3, 0xc8, 0x28, 841 | 0xc5, 0x69, 0x48, 0xa0, 0xf7, 0x74, 0x1a, 0x91, 0x03, 0xa8, 0x4e, 0x71, 0x8e, 0x02, 0xc7, 0x94, 842 | 0x19, 0x9b, 0x4d, 0xad, 0x55, 0xf1, 0x2a, 0x09, 0xe0, 0x32, 0x72, 0x04, 0x75, 0xca, 0x30, 0xf4, 843 | 0xc5, 0x8c, 0x06, 0xe3, 0xd9, 0xd4, 0x28, 0x27, 0x17, 0x94, 0x61, 0xce, 0xd4, 0xea, 0xc3, 0xee, 844 | 0x3d, 0x19, 0xa9, 0xe0, 0xff, 0x61, 0x13, 0xc3, 0x90, 0x86, 0xa9, 0x8c, 0x24, 0xc8, 0xb1, 0x15, 845 | 0xf2, 0x6c, 0x87, 0x60, 0x0e, 0x97, 0x8c, 0xd1, 0x50, 0xe0, 0xd4, 0x55, 0x38, 0x57, 0x77, 0xeb, 846 | 0xc3, 0xc1, 0xda, 0x6c, 0x7a, 0xea, 0x6b, 0x28, 0x52, 0xc6, 0x0d, 0xad, 0x59, 0x6c, 0xd5, 0x3a, 847 | 0x66, 0x3b, 0xb1, 0x47, 0x3b, 0xbf, 0xc3, 0x93, 0x65, 0xab, 0x1e, 0x0b, 0xf7, 0x7a, 0xb4, 0xe6, 848 | 0x40, 0xf2, 0x1b, 0x88, 0x0e, 0xc5, 0x5b, 0x8c, 0x52, 0x35, 0x72, 0x29, 0x77, 0xdf, 0xf9, 0xf3, 849 | 0xa5, 0x7a, 0x8d, 0x24, 0x20, 0x6d, 0xa8, 0x4c, 0x7c, 0x81, 0xd7, 0x34, 0x8c, 0xe2, 0x97, 0x68, 850 | 0x74, 0x88, 0x6a, 0xc3, 0x65, 0xdd, 0x34, 0xe3, 0x65, 0x35, 0xd6, 0x0e, 0x6c, 0xf7, 0xee, 0x30, 851 | 0x10, 0x99, 0xc2, 0x5f, 0x1a, 0x34, 0x14, 0x92, 0xaa, 0x3a, 0x01, 0x40, 0x89, 0x8c, 0x45, 0xc4, 852 | 0x12, 0x5f, 0x34, 0x3a, 0xbb, 0x8a, 0x35, 0xae, 0x1d, 0x45, 0x0c, 0xbd, 0x2a, 0xaa, 0x25, 0x31, 853 | 0x60, 0x8b, 0x2f, 0x17, 0x0b, 0x3f, 0x8c, 0xd2, 0xee, 0x54, 0x28, 0x33, 0x53, 0x14, 0xfe, 0x6c, 854 | 0xce, 0x53, 0xa3, 0xa8, 0x30, 0xf7, 0x36, 0xa5, 0xdc, 0xdb, 0x1c, 0x7f, 0x06, 0x58, 0x89, 0x20, 855 | 0x35, 0xd8, 0x72, 0x06, 0xc3, 0x91, 0xdd, 0xef, 0xeb, 0x1b, 0x64, 0x0f, 0xc8, 0xd0, 0x3e, 0xbf, 856 | 0xe8, 0xf7, 0xc6, 0xf6, 0xc5, 0x45, 0xdf, 0xe9, 0xda, 0x23, 0xc7, 0x1d, 0xe8, 0x1a, 0xd9, 0x86, 857 | 0x6a, 0xd7, 0x1d, 0x9c, 0x3a, 0x67, 0x97, 0x5e, 0x4f, 0x2f, 0x90, 0x3a, 0x54, 0x3e, 0xda, 0x7d, 858 | 0xe7, 0x83, 0x3d, 0xea, 0xe9, 0x45, 0x02, 0x50, 0xee, 0x5e, 0x0e, 0x47, 0xee, 0xb9, 0x5e, 0x3a, 859 | 0x3e, 0x86, 0x6a, 0x26, 0x85, 0x54, 0xa0, 0xe4, 0x0c, 0x4e, 0x5d, 0x7d, 0x43, 0xae, 0x3e, 0xd9, 860 | 0x9e, 0x64, 0xaa, 0xc2, 0x66, 0xcf, 0xf3, 0x5c, 0x4f, 0x2f, 0x74, 0x7e, 0x17, 0xa1, 0x26, 0x47, 861 | 0x6c, 0x88, 0xe1, 0xdd, 0x6c, 0x82, 0xe4, 0x2b, 0x90, 0xfc, 0x88, 0x92, 0x23, 0x75, 0x45, 0x8f, 862 | 0xfe, 0x0d, 0xa6, 0xf5, 0x54, 0x49, 0x3a, 0xe1, 0x1b, 0xe4, 0x1d, 0x54, 0xd4, 0x40, 0x93, 0xe7, 863 | 0x6a, 0xc7, 0x83, 0xa9, 0x37, 0x8d, 0x7c, 0x22, 0x23, 0x38, 0x83, 0x46, 0x3c, 0x21, 0x2b, 0x3b, 864 | 0x65, 0xd5, 0x0f, 0x3f, 0x00, 0x73, 0x7f, 0x4d, 0x26, 0x23, 0xfa, 0x06, 0xff, 0xad, 0xb1, 0x3f, 865 | 0xb1, 0x1e, 0x77, 0xba, 0xf2, 0x95, 0xf9, 0xf2, 0xc9, 0x9a, 0xec, 0x04, 0x1b, 0xea, 0x43, 0x11, 866 | 0xa2, 0xbf, 0x48, 0x3c, 0x48, 0x9e, 0xfd, 0xe3, 0xb3, 0x8c, 0x6d, 0xef, 0x21, 0xac, 0x08, 0x4e, 867 | 0xb4, 0xab, 0x72, 0xfc, 0x39, 0xbf, 0xf9, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x27, 0xa3, 0x6e, 0x5a, 868 | 0xad, 0x05, 0x00, 0x00, 869 | } 870 | --------------------------------------------------------------------------------