diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0f3d98a..3e234f9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,149 +1,151 @@ -name: Meshery OSM +name: Meshery-OSM on: push: branches: - - 'master' + - "*" tags: - - 'v*' + - "v*" pull_request: branches: - - 'master' - + - master jobs: - golangci: - name: golangci-lint + lint: + name: Check & Review code runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: golangci-lint - uses: golangci/golangci-lint-action@v1 + - name: Check out code + uses: actions/checkout@master with: - # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.29 - - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true - server-tests: - needs: [tests-ui, golangci, build-backend, build-ui] - name: Server tests + fetch-depth: 1 + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: ${{ secrets.GO_VERSION }} + - run: GOPROXY=direct GOSUMDB=off go get -u golang.org/x/lint/golint; go list ./istio/... | grep -v /vendor/ | xargs -L1 /home/runner/go/bin/golint -set_exit_status + error_check: + name: Error check runs-on: ubuntu-latest steps: - - name: Check out code - uses: actions/checkout@master - with: - fetch-depth: 1 - - name: Setup Go - uses: actions/setup-go@v1 - with: - go-version: ${{ secrets.GO_VERSION }} - - name: Setup Cache - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go test -tags draft ./... - build-backend: - name: Backend build + - name: Check out code + uses: actions/checkout@master + with: + fetch-depth: 1 + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: ${{ secrets.GO_VERSION }} + - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go get -u github.com/kisielk/errcheck; /home/runner/go/bin/errcheck -tags draft ./... + static_check: + name: Static check runs-on: ubuntu-latest steps: - - name: Check out code - uses: actions/checkout@master - with: + - name: Check out code + uses: actions/checkout@master + with: + fetch-depth: 1 + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: ${{ secrets.GO_VERSION }} + - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go get -u honnef.co/go/tools/cmd/staticcheck; /home/runner/go/bin/staticcheck -tags draft -checks all ./istio/... # https://staticcheck.io/docs/checks + vet: + name: Vet + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@master + with: + fetch-depth: 1 + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: ${{ secrets.GO_VERSION }} + - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go vet -tags draft ./... + sec_check: + name: Security check + runs-on: ubuntu-latest + env: + GO111MODULE: on + steps: + - name: Check out code + uses: actions/checkout@v2 + with: + fetch-depth: 1 + - name: Run Gosec Security Scanner + uses: securego/gosec@master + with: + args: ./... -exclude=G301,G304,G107,G101,G110 + tests: + # needs: [lint, error_check, static_check, vet, sec_check] + name: Tests + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@master + with: fetch-depth: 1 - - name: Setup Go - uses: actions/setup-go@v1 - with: + - name: Setup Go + uses: actions/setup-go@v1 + with: go-version: ${{ secrets.GO_VERSION }} - - name: Setup Cache - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go build -tags draft ./cmd/main.go - build-ui: - name: UI build + - name: Create cluster using KinD + uses: engineerd/setup-kind@v0.3.0 + with: + version: "v0.7.0" + - run: | + export CURRENTCONTEXT="$(kubectl config current-context)" + echo "current-context:" ${CURRENTCONTEXT} + export KUBECONFIG="${HOME}/.kube/config" + echo "environment-kubeconfig:" ${KUBECONFIG} + GOPROXY=direct GOSUMDB=off GO111MODULE=on go test ./... + build: + name: Build check runs-on: ubuntu-latest + # needs: [lint, error_check, static_check, vet, sec_check, tests] steps: - - name: Check out code - uses: actions/checkout@master - with: - fetch-depth: 1 - - uses: actions/setup-node@v1 - with: - node-version: ${{ secrets.NODE_VERSION }} - - uses: actions/cache@v1 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - run: | - cd ui - npm i - npm run build && npm run export - cd .. - cd provider-ui - npm i - npm run build && npm run export - tests-ui: - name: UI tests + - name: Check out code + uses: actions/checkout@master + with: + fetch-depth: 1 + - name: Setup Go + uses: actions/setup-go@v1 + with: + go-version: ${{ secrets.GO_VERSION }} + - run: GOPROXY=direct GOSUMDB=off GO111MODULE=on go build . + docker: + name: Docker build and push runs-on: ubuntu-latest + # needs: [build, build_release] steps: - name: Check out code + if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() uses: actions/checkout@master with: fetch-depth: 1 - - uses: actions/setup-node@v1 - with: - node-version: ${{ secrets.NODE_VERSION }} - - uses: actions/cache@v1 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - run: | - cd ui - npm i - npm test - cd .. - cd provider-ui - npm i - npm test - cd .. - mesheryctl_build: - name: Mesheryctl build & release - runs-on: macos-latest - needs: [server-tests] - steps: - - name: Check out code - uses: actions/checkout@master - - name: Unshallow - run: git fetch --prune --unshallow - - name: Set up Go - uses: actions/setup-go@v1 - with: - go-version: ${{ secrets.GO_VERSION }} - - name: Setup Cache - uses: actions/cache@v1 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - name: goreleaser WITHOUT tag - uses: goreleaser/goreleaser-action@v1 - if: success() && startsWith(github.ref, 'refs/tags/') == false + - name: Docker login + if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() + uses: azure/container-actions/docker-login@master with: - version: latest - args: release --snapshot --skip-publish --rm-dist + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Docker build & tag + if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() + run: | + DOCKER_BUILDKIT=1 docker build --no-cache -t ${{ secrets.IMAGE_NAME }}:stable-latest . + docker tag ${{ secrets.IMAGE_NAME }}:stable-latest ${{ secrets.IMAGE_NAME }}:${GITHUB_REF/refs\/tags\//}-edge + docker tag ${{ secrets.IMAGE_NAME }}:stable-latest ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_REF/refs\/tags\//} + docker tag ${{ secrets.IMAGE_NAME }}:stable-latest ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_SHA::7} + - name: Docker push + if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() + run: | + docker push ${{ secrets.IMAGE_NAME }}:stable-latest + docker push ${{ secrets.IMAGE_NAME }}:${GITHUB_REF/refs\/tags\//}-edge + docker push ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_REF/refs\/tags\//} + docker push ${{ secrets.IMAGE_NAME }}:stable-${GITHUB_SHA::7} + - name: Docker Hub Description + if: github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') && success() + uses: peter-evans/dockerhub-description@v2.0.0 + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + DOCKERHUB_REPOSITORY: ${{ secrets.IMAGE_NAME }} diff --git a/go.mod b/go.mod index 01d4fbf3..bc9f2a83 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,26 @@ module github.com/layer5io/meshery-osm -go 1.3 +go 1.13 -replace github.com/kudobuilder/kuttl => github.com/layer5io/kuttl v0.4.1-0.20200806180306-b7e46afd657f +replace ( + github.com/kudobuilder/kuttl => github.com/layer5io/kuttl v0.4.1-0.20200806180306-b7e46afd657f + vbom.ml/util => github.com/fvbommel/util v0.0.0-20180919145318-efcd4e0f9787 +) require ( github.com/Azure/go-autorest/autorest/adal v0.9.0 // indirect github.com/golang/protobuf v1.4.2 github.com/gophercloud/gophercloud v0.4.0 // indirect - github.com/layer5io/gokit v0.1.5 + github.com/layer5io/gokit v0.1.12 + github.com/layer5io/learn-layer5/smi-conformance v0.0.0-20200916172547-79cf11334bd7 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.6.0 golang.org/x/net v0.0.0-20200707034311-ab3426394381 google.golang.org/grpc v1.31.0 gopkg.in/yaml.v2 v2.3.0 + helm.sh/helm/v3 v3.3.4 + k8s.io/api v0.18.8 + k8s.io/apimachinery v0.18.8 k8s.io/client-go v0.18.8 + rsc.io/letsencrypt v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 8d7dc54d..d9a11946 100644 --- a/go.sum +++ b/go.sum @@ -223,6 +223,7 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fvbommel/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:AlRx4sdoz6EdWGYPMeunQWYf46cKnq7J4iVvLgyb5cY= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -367,6 +368,7 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -384,6 +386,7 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= @@ -439,6 +442,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= @@ -478,6 +482,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -487,8 +493,8 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= -github.com/layer5io/gokit v0.1.5 h1:CiprdNuj/2scRygSbH4b3AuK0suzDIkWPOEe2xwa46Q= -github.com/layer5io/gokit v0.1.5/go.mod h1:RWSxqCEoIeTyD+sn6MMOunZJxfAIdkTRgrdeYTI2RL0= +github.com/layer5io/gokit v0.1.12 h1:QGfoOHfiOpvPaCg1sGFM8ZuatXsgCkWGPD7GVVVQMyY= +github.com/layer5io/gokit v0.1.12/go.mod h1:kqwXJ5JZqHv74UCH1pVyDdpLT8muaUyRVu58WWu6wcY= github.com/layer5io/kuttl v0.4.1-0.20200806180306-b7e46afd657f/go.mod h1:UmrVd7x+bNVKrpmKgTtfRiTKHZeNPcMjQproJ0vGwhE= github.com/layer5io/learn-layer5/smi-conformance v0.0.0-20200916172547-79cf11334bd7 h1:jglAwWM8pbUN43HL3tpFYPkWLFNpj1/ZsJISdqKhavg= github.com/layer5io/learn-layer5/smi-conformance v0.0.0-20200916172547-79cf11334bd7/go.mod h1:LpewBZnN0QDRcC2fDiBVK+iByfFyf2HJM1B2h0rTMZo= @@ -897,6 +903,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1028,8 +1036,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -helm.sh/helm/v3 v3.3.1 h1:uc+ZUthJnWNSwqyIv1KCdQm0ewi0eAf6oRaWG2X1oo0= -helm.sh/helm/v3 v3.3.1/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU= +helm.sh/helm/v3 v3.3.4 h1:tbad6WQVMxEw1HlVBvI2rQqOblmI5lgXOrWAMwJ198M= +helm.sh/helm/v3 v3.3.4/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1112,4 +1120,3 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/osm/smi/error.go b/osm/smi/error.go new file mode 100644 index 00000000..65b17b3c --- /dev/null +++ b/osm/smi/error.go @@ -0,0 +1,32 @@ +package smi + +import ( + "fmt" + + "github.com/layer5io/gokit/errors" +) + +// ErrSmiInit is the error for smi init method +func ErrSmiInit(des string) error { + return errors.New(errors.ErrSmiInit, des) +} + +// ErrInstallSmi is the error for installing smi tool +func ErrInstallSmi(err error) error { + return errors.New(errors.ErrInstallSmi, fmt.Sprintf("Error installing smi tool: %s", err.Error())) +} + +// ErrConnectSmi is the error for connecting to smi tool +func ErrConnectSmi(err error) error { + return errors.New(errors.ErrConnectSmi, fmt.Sprintf("Error connecting to smi tool: %s", err.Error())) +} + +// ErrRunSmi is the error for running conformance test +func ErrRunSmi(err error) error { + return errors.New(errors.ErrRunSmi, fmt.Sprintf("Error running smi tool: %s", err.Error())) +} + +// ErrDeleteSmi is the error for deleteing smi tool +func ErrDeleteSmi(err error) error { + return errors.New(errors.ErrDeleteSmi, fmt.Sprintf("Error deleting smi tool: %s", err.Error())) +} diff --git a/osm/smi/smi.go b/osm/smi/smi.go new file mode 100644 index 00000000..e9846409 --- /dev/null +++ b/osm/smi/smi.go @@ -0,0 +1,272 @@ +package smi + +import ( + "context" + "fmt" + "net" + "os" + "time" + + "github.com/layer5io/learn-layer5/smi-conformance/conformance" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart/loader" + "helm.sh/helm/v3/pkg/kube" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + + "github.com/layer5io/gokit/utils" +) + +var ( + name = "smi-conformance" + helmPath = "https://github.com/layer5io/learn-layer5/raw/75a6b26cf5a5defaa0629e9bd55780fa52a82d2b/charts/smi-conformance-0.1.2.tgz" + namespace = "meshery" +) + +type SmiTest struct { + id string + adaptorVersion string + adaptorName string + ctx context.Context + kubeClient *kubernetes.Clientset + kubeConfigPath string + smiAddress string + annotations map[string]string + labels map[string]string +} + +type Response struct { + Id string `json:"id,omitempty"` + Date string `json:"date,omitempty"` + MeshName string `json:"mesh_name,omitempty"` + MeshVersion string `json:"mesh_version,omitempty"` + CasesPassed string `json:"cases_passed,omitempty"` + PassingPercentage string `json:"passing_percentage,omitempty"` + Status string `json:"status,omitempty"` + MoreDetails []*Detail `json:"more_details,omitempty"` +} + +type Detail struct { + SmiSpecification string `json:"smi_specification,omitempty"` + SmiVersion string `json:"smi_version,omitempty"` + Time string `json:"time,omitempty"` + Assertions string `json:"assertions,omitemtpy"` + Result string `json:"result,omitempty"` + Reason string `json:"reason,omitempty"` + Capability string `json:"capability,omitempty"` + Status string `json:"status,omitempty"` +} + +func New(ctx context.Context, id string, version string, name string, client *kubernetes.Clientset) (*SmiTest, error) { + + if len(name) < 2 { + return nil, ErrSmiInit("Adaptor name is nil") + } + + if client == nil { + return nil, ErrSmiInit("Client set is nil") + } + + test := &SmiTest{ + ctx: ctx, + id: id, + adaptorVersion: version, + kubeClient: client, + kubeConfigPath: fmt.Sprintf("%s/.kube/config", utils.GetHome()), + adaptorName: name, + labels: make(map[string]string, 0), + annotations: make(map[string]string, 0), + } + + return test, nil +} + +func (test *SmiTest) Run(labels, annotations map[string]string) (Response, error) { + + if labels != nil { + test.labels = labels + } + + if annotations != nil { + test.annotations = annotations + } + + response := Response{ + Id: test.id, + Date: time.Now().String(), + MeshName: test.adaptorName, + MeshVersion: test.adaptorVersion, + CasesPassed: "0", + PassingPercentage: "0", + Status: "deploying", + } + + err := test.installConformanceTool() + if err != nil { + response.Status = "installing" + return response, ErrInstallSmi(err) + } + + err = test.connectConformanceTool() + if err != nil { + response.Status = "connecting" + return response, ErrConnectSmi(err) + } + + err = test.runConformanceTest(&response) + if err != nil { + response.Status = "running" + return response, ErrRunSmi(err) + } + + err = test.deleteConformanceTool() + if err != nil { + response.Status = "deleting" + return response, ErrDeleteSmi(err) + } + + response.Status = "completed" + return response, nil +} + +// installConformanceTool installs the smi conformance tool +func (test *SmiTest) installConformanceTool() error { + + _, err := test.kubeClient.CoreV1().Namespaces().Create(context.TODO(), &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + Annotations: map[string]string{ + "meta.helm.sh/release-name": name, + "meta.helm.sh/release-namespace": namespace, + }, + Labels: map[string]string{ + "app.kubernetes.io/managed-by": "Helm", + }, + }}, metav1.CreateOptions{}) + if err != nil { + return err + } + + localpath := "/tmp/smi-conformance.tar.gz" + err = utils.DownloadFile(localpath, helmPath) + if err != nil { + return err + } + + chart, err := loader.Load(localpath) + if err != nil { + return err + } + + actionConfig := &action.Configuration{} + if err := actionConfig.Init(kube.GetConfig(test.kubeConfigPath, "", namespace), namespace, os.Getenv("HELM_DRIVER"), nil); err != nil { + return err + } + + iCli := action.NewInstall(actionConfig) + iCli.Namespace = namespace + iCli.ReleaseName = name + _, err = iCli.Run(chart, nil) + if err != nil { + return err + } + + time.Sleep(10 * time.Second) // Required for all the resources to be created + + return nil +} + +// deleteConformanceTool deletes the smi conformance tool +func (test *SmiTest) deleteConformanceTool() error { + err := test.kubeClient.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{}) + if err != nil { + return err + } + return nil +} + +// connectConformanceTool initiates the connection +func (test *SmiTest) connectConformanceTool() error { + var host string + var port int32 + + svc, err := test.kubeClient.CoreV1().Services(namespace).Get(test.ctx, name, metav1.GetOptions{}) + if err != nil { + return err + } + + nodes, err := test.kubeClient.CoreV1().Nodes().List(test.ctx, metav1.ListOptions{}) + if err != nil { + return err + } + addresses := make(map[string]string, 0) + for _, addr := range nodes.Items[0].Status.Addresses { + addresses[string(addr.Type)] = addr.Address + } + host = addresses["ExternalIP"] + port = svc.Spec.Ports[0].NodePort + if tcpCheck(addresses["InternalIP"], port) { + host = addresses["InternalIP"] + } + + test.smiAddress = fmt.Sprintf("%s:%d", host, port) + return nil +} + +func tcpCheck(ip string, port int32) bool { + timeout := 5 * time.Second + conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), timeout) + if err != nil { + return false + } + if conn != nil { + return true + } + return false +} + +// runConformanceTest runs the conformance test +func (test *SmiTest) runConformanceTest(response *Response) error { + + cClient, err := conformance.CreateClient(context.TODO(), test.smiAddress) + if err != nil { + return err + } + + result, err := cClient.CClient.RunTest(context.TODO(), &conformance.Request{ + Annotations: test.annotations, + Labels: test.labels, + Meshname: test.adaptorName, + Meshversion: test.adaptorVersion, + }) + if err != nil { + return err + } + + response.CasesPassed = result.Casespassed + response.PassingPercentage = result.Passpercent + + details := make([]*Detail, 0) + + for _, d := range result.Details { + details = append(details, &Detail{ + SmiSpecification: d.Smispec, + Time: d.Time, + Assertions: d.Assertions, + Result: d.Result, + Reason: d.Reason, + Capability: d.Capability, + Status: d.Status, + }) + } + + response.MoreDetails = details + + err = cClient.Close() + if err != nil { + return err + } + + return nil +} diff --git a/osm/smi_conformance.go b/osm/smi_conformance.go index d35f901d..8a0f1b18 100644 --- a/osm/smi_conformance.go +++ b/osm/smi_conformance.go @@ -5,8 +5,8 @@ import ( "encoding/json" "fmt" - "github.com/layer5io/gokit/smi" "github.com/layer5io/meshery-osm/meshes" + "github.com/layer5io/meshery-osm/osm/smi" ) func (iClient *Client) validateSMIConformance(id string, version string) error {