diff --git a/.github/workflows/pre_main.yaml b/.github/workflows/pre_main.yaml index 8609747b..c6263d5f 100644 --- a/.github/workflows/pre_main.yaml +++ b/.github/workflows/pre_main.yaml @@ -28,7 +28,33 @@ jobs: version: v1.52.2 # Optional: working directory, useful for monorepos - # working-directory: somedir + working-directory: collector-framework + + # Optional: golangci-lint command line arguments. + args: --timeout=5m0s + + # Optional: show only new issues if it's a pull request. The default value is `false`. + # only-new-issues: true + + # Optional: if set to true then the all caching functionality will be complete disabled, + # takes precedence over all other caching options. + # skip-cache: true + + # Optional: if set to true then the action don't cache or restore ~/go/pkg. + # skip-pkg-cache: true + + # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. + # skip-build-cache: true + + + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version + version: v1.52.2 + + # Optional: working directory, useful for monorepos + working-directory: tgm-collector # Optional: golangci-lint command line arguments. args: --timeout=5m0s @@ -59,11 +85,18 @@ jobs: uses: actions/checkout@v3 - name: Set up ginkgo + working-directory: collector-framework run: make install-tools - - name: Run package tests + - name: Run collector-framework package tests + working-directory: collector-framework run: ginkgo pkg/... + - name: Run tgm-collector package tests + working-directory: tgm-collector + run: ginkgo pkg/... + + yamllint: name: Lint YAML files runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0b96ba70..e080ef3d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,13 +7,6 @@ repos: - id: check-yaml - id: check-added-large-files - - repo: https://github.com/psf/black - rev: 23.3.0 - hooks: - - id: black - types: - - python - - repo: local hooks: - id: license-header @@ -23,13 +16,25 @@ repos: pass_filenames: false - id: golangci-lint - name: golangci-lint must pass + name: golangci-lint (tgm-collector) must pass + language: system + entry: bash -c 'cd tgm-collector && make lint' + pass_filenames: false + + - id: go-mod-tidy + name: run go mod tidy (tgm-collector) + language: system + entry: bash -c 'cd tgm-collector && go mod tidy' + pass_filenames: false + + - id: golangci-lint + name: golangci-lint (collector-framework) must pass language: system - entry: make lint + entry: bash -c 'cd collector-framework && make lint' pass_filenames: false - id: go-mod-tidy - name: run go mod tidy + name: run go mod tidy (collector-framework) language: system - entry: go mod tidy + entry: bash -c 'cd collector-framework && go mod tidy' pass_filenames: false diff --git a/Containerfile b/collector-framework/Containerfile similarity index 100% rename from Containerfile rename to collector-framework/Containerfile diff --git a/LICENSE b/collector-framework/LICENSE similarity index 100% rename from LICENSE rename to collector-framework/LICENSE diff --git a/Makefile b/collector-framework/Makefile similarity index 100% rename from Makefile rename to collector-framework/Makefile diff --git a/collector-framework/README.md b/collector-framework/README.md new file mode 100644 index 00000000..5e33d0bb --- /dev/null +++ b/collector-framework/README.md @@ -0,0 +1,7 @@ +# Collector framework + +This is a framework for making it easier for people to build collectors. +It provides a basic framework just create your collector, register it, +then trigger the runner from a entry point of your choice. + +See `tgm-collectors` for an example. diff --git a/doc/implementing_a_collector.md b/collector-framework/doc/implementing_a_collector.md similarity index 99% rename from doc/implementing_a_collector.md rename to collector-framework/doc/implementing_a_collector.md index 7e4fcd73..06a62b8e 100644 --- a/doc/implementing_a_collector.md +++ b/collector-framework/doc/implementing_a_collector.md @@ -75,7 +75,7 @@ package collectors import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" ) const ( AnnouncementCollectorName = "MyCustomerAnouncer" diff --git a/doc/implementing_a_fetcher.md b/collector-framework/doc/implementing_a_fetcher.md similarity index 100% rename from doc/implementing_a_fetcher.md rename to collector-framework/doc/implementing_a_fetcher.md diff --git a/go.mod b/collector-framework/go.mod similarity index 96% rename from go.mod rename to collector-framework/go.mod index 4cc5102f..55865084 100644 --- a/go.mod +++ b/collector-framework/go.mod @@ -1,4 +1,4 @@ -module github.com/redhat-partner-solutions/vse-sync-collection-tools +module github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework go 1.18 @@ -37,7 +37,6 @@ require ( github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/pretty v0.3.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -45,7 +44,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openshift/api v0.0.0-20230120195050-6ba31fa438f2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/rogpeppe/go-internal v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.5.0 // indirect diff --git a/collector-framework/go.sum b/collector-framework/go.sum new file mode 100644 index 00000000..430ddc0b --- /dev/null +++ b/collector-framework/go.sum @@ -0,0 +1,303 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= +github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= +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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/icza/backscanner v0.0.0-20230330133933-bf6beb754c70 h1:xrd41BUTgqxyYFfFwGdt/bnwS8KNYzPraj8WgvJ5NWk= +github.com/icza/backscanner v0.0.0-20230330133933-bf6beb754c70/go.mod h1:GYeBD1CF7AqnKZK+UCytLcY3G+UKo0ByXX/3xfdNyqQ= +github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= +github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= +github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= +github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= +github.com/openshift/api v0.0.0-20230120195050-6ba31fa438f2 h1:+nw0/d4spq880W7S74Twi5YU2ulsl3/a9o4OEZptYp0= +github.com/openshift/api v0.0.0-20230120195050-6ba31fa438f2/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= +github.com/openshift/client-go v0.0.0-20230120202327-72f107311084 h1:66uaqNwA+qYyQDwsMWUfjjau8ezmg1dzCqub13KZOcE= +github.com/openshift/client-go v0.0.0-20230120202327-72f107311084/go.mod h1:M3h9m001PWac3eAudGG3isUud6yBjr5XpzLYLLTlHKo= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= +k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= +k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= +k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= +k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= +k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= +k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= +k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d h1:oFDpQ7FfzinCtrFOl4izwOWsdTprlS2A9IXBENMW0UA= +k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/kubectl v0.26.1 h1:K8A0Jjlwg8GqrxOXxAbjY5xtmXYeYjLU96cHp2WMQ7s= +k8s.io/kubectl v0.26.1/go.mod h1:miYFVzldVbdIiXMrHZYmL/EDWwJKM+F0sSsdxsATFPo= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/hack/logs.go b/collector-framework/hack/logs.go similarity index 100% rename from hack/logs.go rename to collector-framework/hack/logs.go diff --git a/pkg/callbacks/callbacks.go b/collector-framework/pkg/callbacks/callbacks.go similarity index 100% rename from pkg/callbacks/callbacks.go rename to collector-framework/pkg/callbacks/callbacks.go diff --git a/pkg/callbacks/callbacks_test.go b/collector-framework/pkg/callbacks/callbacks_test.go similarity index 98% rename from pkg/callbacks/callbacks_test.go rename to collector-framework/pkg/callbacks/callbacks_test.go index 45604827..663acbb9 100644 --- a/pkg/callbacks/callbacks_test.go +++ b/collector-framework/pkg/callbacks/callbacks_test.go @@ -10,7 +10,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" ) func NewTestFile() *testFile { diff --git a/pkg/clients/clients_test.go b/collector-framework/pkg/clients/clients_test.go similarity index 97% rename from pkg/clients/clients_test.go rename to collector-framework/pkg/clients/clients_test.go index 1e806b51..709ddc46 100644 --- a/pkg/clients/clients_test.go +++ b/collector-framework/pkg/clients/clients_test.go @@ -8,7 +8,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) const ( diff --git a/pkg/clients/clientset.go b/collector-framework/pkg/clients/clientset.go similarity index 99% rename from pkg/clients/clientset.go rename to collector-framework/pkg/clients/clientset.go index 1e0bc48b..5154a6de 100644 --- a/pkg/clients/clientset.go +++ b/collector-framework/pkg/clients/clientset.go @@ -16,7 +16,7 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) // A Clientset contains clients for the different k8s API groups in one place diff --git a/pkg/clients/command.go b/collector-framework/pkg/clients/command.go similarity index 100% rename from pkg/clients/command.go rename to collector-framework/pkg/clients/command.go diff --git a/pkg/clients/command_test.go b/collector-framework/pkg/clients/command_test.go similarity index 98% rename from pkg/clients/command_test.go rename to collector-framework/pkg/clients/command_test.go index a5eacf17..c28f4efd 100644 --- a/pkg/clients/command_test.go +++ b/collector-framework/pkg/clients/command_test.go @@ -8,7 +8,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) var _ = Describe("Cmd", func() { diff --git a/pkg/clients/exec_command.go b/collector-framework/pkg/clients/exec_command.go similarity index 96% rename from pkg/clients/exec_command.go rename to collector-framework/pkg/clients/exec_command.go index 34ba9c46..d016cf37 100644 --- a/pkg/clients/exec_command.go +++ b/collector-framework/pkg/clients/exec_command.go @@ -20,10 +20,17 @@ import ( ) const ( - startTimeout = 5 * time.Second + startTimeout = 2 * time.Minute deletionTimeout = 10 * time.Minute ) +type APIContext interface { + GetNamespace() string + GetPodName() string + GetContainerName() string + GetClientset() *Clientset +} + type ExecContext interface { ExecCommand([]string) (string, string, error) ExecCommandStdIn([]string, bytes.Buffer) (string, string, error) @@ -40,7 +47,7 @@ type ContainerExecContext struct { podNamePrefix string } -func (c *ContainerExecContext) refresh() error { +func (c *ContainerExecContext) Refresh() error { newPodname, err := c.clientset.FindPodNameFromPrefix(c.namespace, c.podNamePrefix) if err != nil { return err @@ -79,6 +86,10 @@ func (c *ContainerExecContext) GetContainerName() string { return c.containerName } +func (c *ContainerExecContext) GetClientset() *Clientset { + return c.clientset +} + //nolint:lll,funlen // allow slightly long function definition and function length func (c *ContainerExecContext) execCommand(command []string, buffInPtr *bytes.Buffer) (stdout, stderr string, err error) { commandStr := command @@ -134,7 +145,7 @@ func (c *ContainerExecContext) execCommand(command []string, buffInPtr *bytes.Bu if err != nil { if k8sErrors.IsNotFound(err) { log.Debugf("Pod %s was not found, likely restarted so refreshing context", c.GetPodName()) - refreshErr := c.refresh() + refreshErr := c.Refresh() if refreshErr != nil { log.Debug("Failed to refresh container context", refreshErr) } diff --git a/pkg/clients/exec_command_test.go b/collector-framework/pkg/clients/exec_command_test.go similarity index 98% rename from pkg/clients/exec_command_test.go rename to collector-framework/pkg/clients/exec_command_test.go index 4eb012ce..81feb761 100644 --- a/pkg/clients/exec_command_test.go +++ b/collector-framework/pkg/clients/exec_command_test.go @@ -14,8 +14,8 @@ import ( fakeK8s "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/tools/remotecommand" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/testutils" ) var notATestPod = &v1.Pod{ diff --git a/pkg/clients/test_files/kubeconfig b/collector-framework/pkg/clients/test_files/kubeconfig similarity index 100% rename from pkg/clients/test_files/kubeconfig rename to collector-framework/pkg/clients/test_files/kubeconfig diff --git a/collector-framework/pkg/cmd/collect.go b/collector-framework/pkg/cmd/collect.go new file mode 100644 index 00000000..89a2645a --- /dev/null +++ b/collector-framework/pkg/cmd/collect.go @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package cmd + +import ( + "fmt" + "strings" + "time" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/runner" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" +) + +const ( + defaultDuration string = "1000s" + defaultPollInterval int = 1 + defaultDevInfoInterval int = 60 +) + +type CollectorArgFunc func([]string) map[string]map[string]any + +var ( + requestedDurationStr string + pollInterval int + devInfoAnnouceInterval int + collectorNames []string + runFunc CollectorArgFunc +) + +func SetCollecterArgsFunc(f CollectorArgFunc) { + runFunc = f +} + +// CollectCmd represents the collect command +var CollectCmd = &cobra.Command{ + Use: "collect", + Short: "Run the collector tool", + Long: `Run the collector tool to gather data from your target cluster`, + Run: func(cmd *cobra.Command, args []string) { + + collectionRunner := runner.NewCollectorRunner(collectorNames) + + requestedDuration, err := time.ParseDuration(requestedDurationStr) + if requestedDuration.Nanoseconds() < 0 { + log.Panicf("Requested duration must be positive") + } + utils.IfErrorExitOrPanic(err) + + collectorArgs := make(map[string]map[string]any) + if runFunc != nil { + log.Debug("No runFunc function is defined") + collectorArgs = runFunc(collectorNames) + } + + collectionRunner.Run( + kubeConfig, + outputFile, + requestedDuration, + pollInterval, + devInfoAnnouceInterval, + useAnalyserJSON, + collectorArgs, + ) + }, +} + +func init() { //nolint:funlen // Allow this to get a little long + RootCmd.AddCommand(CollectCmd) + + AddKubeconfigFlag(CollectCmd) + AddOutputFlag(CollectCmd) + AddFormatFlag(CollectCmd) + + CollectCmd.Flags().StringVarP( + &requestedDurationStr, + "duration", + "d", + defaultDuration, + "A positive duration string sequence of decimal numbers and a unit suffix, such as \"300ms\", \"1.5h\" or \"2h45m\"."+ + " Valid time units are \"s\", \"m\", \"h\".", + ) + CollectCmd.Flags().IntVarP( + &pollInterval, + "rate", + "r", + defaultPollInterval, + "Poll interval for querying the cluster. The value will be polled once every interval. "+ + "Using --rate 10 will cause the value to be polled once every 10 seconds", + ) + CollectCmd.Flags().IntVarP( + &devInfoAnnouceInterval, + "announce", + "a", + defaultDevInfoInterval, + "interval at which to emit the device info summary to the targeted output.", + ) + defaultCollectorNames := make([]string, 0) + defaultCollectorNames = append(defaultCollectorNames, runner.All) + CollectCmd.Flags().StringSliceVarP( + &collectorNames, + "collector", + "s", + defaultCollectorNames, + fmt.Sprintf( + "the collectors you wish to run (case-insensitive):\n"+ + "\trequired collectors: %s (will be automatically added)\n"+ + "\toptional collectors: %s", + strings.Join(runner.RequiredCollectorNames, ", "), + strings.Join(runner.OptionalCollectorNames, ", "), + ), + ) +} diff --git a/pkg/cmd/common.go b/collector-framework/pkg/cmd/common.go similarity index 75% rename from pkg/cmd/common.go rename to collector-framework/pkg/cmd/common.go index 81fe50d2..678d956d 100644 --- a/pkg/cmd/common.go +++ b/collector-framework/pkg/cmd/common.go @@ -5,14 +5,13 @@ package cmd import ( "github.com/spf13/cobra" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) var ( kubeConfig string outputFile string useAnalyserJSON bool - ptpInterface string ) func AddKubeconfigFlag(targetCmd *cobra.Command) { @@ -35,8 +34,10 @@ func AddFormatFlag(targetCmd *cobra.Command) { ) } -func AddInterfaceFlag(targetCmd *cobra.Command) { - targetCmd.Flags().StringVarP(&ptpInterface, "interface", "i", "", "Name of the PTP interface") - err := targetCmd.MarkFlagRequired("interface") - utils.IfErrorExitOrPanic(err) +func GetKubeConfig() string { + return kubeConfig +} + +func GetUseAnalyserJSON() bool { + return useAnalyserJSON } diff --git a/pkg/cmd/root.go b/collector-framework/pkg/cmd/root.go similarity index 81% rename from pkg/cmd/root.go rename to collector-framework/pkg/cmd/root.go index 6c915ed5..2674dc21 100644 --- a/pkg/cmd/root.go +++ b/collector-framework/pkg/cmd/root.go @@ -8,14 +8,14 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/logging" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/logging" ) var ( logLevel string - // rootCmd represents the base command when called without any subcommands - rootCmd = &cobra.Command{ + // RootCmd represents the base command when called without any subcommands + RootCmd = &cobra.Command{ Use: "vse-sync-testsuite", Short: "A monitoring tool for PTP related metrics", Long: `A monitoring tool for PTP related metrics.`, @@ -28,14 +28,14 @@ var ( // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - err := rootCmd.Execute() + err := RootCmd.Execute() if err != nil { os.Exit(1) } } func init() { - rootCmd.PersistentFlags().StringVarP( + RootCmd.PersistentFlags().StringVarP( &logLevel, "verbosity", "v", diff --git a/collector-framework/pkg/cmd/verifyEnv.go b/collector-framework/pkg/cmd/verifyEnv.go new file mode 100644 index 00000000..0df6d820 --- /dev/null +++ b/collector-framework/pkg/cmd/verifyEnv.go @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package cmd + +import ( + "log" + + "github.com/spf13/cobra" +) + +type verifyFunc func(kubeconfig string, useAnalyserJSON bool) + +var verify verifyFunc + +func SetVerifyFunc(f verifyFunc) { + verify = f +} + +var EnvCmd = &cobra.Command{ + Use: "env", + Short: "environment based actions", + Long: `environment based actions`, +} + +// VerifyEnvCmd represents the verifyEnv command +var VerifyEnvCmd = &cobra.Command{ + Use: "verify", + Short: "verify the environment is ready for collection", + Long: `verify the environment is ready for collection`, + Run: func(cmd *cobra.Command, args []string) { + if verify == nil { + log.Fatal("Verify command was not registered") + } + verify(kubeConfig, useAnalyserJSON) + }, +} + +func init() { + RootCmd.AddCommand(EnvCmd) + EnvCmd.AddCommand(VerifyEnvCmd) + AddKubeconfigFlag(VerifyEnvCmd) + AddOutputFlag(VerifyEnvCmd) + AddFormatFlag(VerifyEnvCmd) +} diff --git a/collector-framework/pkg/collectors/collector.go b/collector-framework/pkg/collectors/collector.go new file mode 100644 index 00000000..14f73e8b --- /dev/null +++ b/collector-framework/pkg/collectors/collector.go @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package collectors + +import ( + "sync" + "time" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" +) + +type Collector interface { + Start() error // Setups any internal state required for collection to happen + Poll(chan PollResult, *utils.WaitGroupCount) // Poll for collectables + CleanUp() error // Stops the collector and cleans up any internal state. It should result in a state that can be started again + GetPollInterval() time.Duration // Returns the collectors polling interval + IsAnnouncer() bool + ScalePollInterval(float64) + ResetPollInterval() +} + +// A union of all values required to be passed into all constructions +type CollectionConstructor struct { + Callback callbacks.Callback + Clientset *clients.Clientset + ErroredPolls chan PollResult + CollectorArgs map[string]map[string]any + PollInterval int + DevInfoAnnouceInterval int +} + +type PollResult struct { + CollectorName string + Errors []error +} + +type baseCollector struct { + Callback callbacks.Callback + pollInterval *LockedInterval + isAnnouncer bool + running bool +} + +func (base *baseCollector) GetPollInterval() time.Duration { + return base.pollInterval.interval() +} + +func (base *baseCollector) ScalePollInterval(factor float64) { + base.pollInterval.scale(factor) +} + +func (base *baseCollector) ResetPollInterval() { + base.pollInterval.reset() +} + +func (base *baseCollector) IsAnnouncer() bool { + return base.isAnnouncer +} + +func (base *baseCollector) Start() error { + base.running = true + return nil +} + +func (base *baseCollector) CleanUp() error { + base.running = false + return nil +} + +func NewBaseCollector( + pollInterval int, + isAnnouncer bool, + callback callbacks.Callback, +) *baseCollector { + return &baseCollector{ + Callback: callback, + isAnnouncer: isAnnouncer, + running: false, + pollInterval: NewLockedInterval(pollInterval), + } +} + +type ExecCollector struct { + *baseCollector + ctx clients.ExecContext +} + +func NewExecCollector( + pollInterval int, + isAnnouncer bool, + callback callbacks.Callback, + ctx clients.ExecContext, +) *ExecCollector { + execCollector := ExecCollector{ + baseCollector: NewBaseCollector( + pollInterval, + isAnnouncer, + callback, + ), + ctx: ctx, + } + return &execCollector +} + +func (col *ExecCollector) GetContext() clients.ExecContext { + return col.ctx +} + +type APICollector struct { + *baseCollector + ctx clients.APIContext +} + +func NewAPICollector( + pollInterval int, + isAnnouncer bool, + callback callbacks.Callback, + ctx clients.APIContext, +) *APICollector { + return &APICollector{ + baseCollector: NewBaseCollector( + pollInterval, + isAnnouncer, + callback, + ), + ctx: ctx, + } +} + +func (col *APICollector) GetContext() clients.APIContext { + return col.ctx +} + +type LockedInterval struct { + current time.Duration + base time.Duration + lock sync.RWMutex +} + +func (li *LockedInterval) interval() time.Duration { + li.lock.RLock() + defer li.lock.RUnlock() + return li.current +} + +func (li *LockedInterval) scale(factor float64) { + li.lock.Lock() + li.current = time.Duration(factor * li.current.Seconds() * float64(time.Second)) + li.lock.Unlock() +} + +func (li *LockedInterval) reset() { + li.lock.Lock() + li.current = li.base + li.lock.Unlock() +} + +func NewLockedInterval(seconds int) *LockedInterval { + return &LockedInterval{ + current: time.Duration(seconds) * time.Second, + base: time.Duration(seconds) * time.Second, + } +} diff --git a/pkg/collectors/log_follower.go b/collector-framework/pkg/collectors/log_follower.go similarity index 76% rename from pkg/collectors/log_follower.go rename to collector-framework/pkg/collectors/log_follower.go index 16db7a9b..5681deef 100644 --- a/pkg/collectors/log_follower.go +++ b/collector-framework/pkg/collectors/log_follower.go @@ -5,6 +5,7 @@ package collectors import ( "bufio" "context" + "errors" "fmt" "io" "os" @@ -17,10 +18,9 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/loglines" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/loglines" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) const ( @@ -55,12 +55,11 @@ var ( // Log aggregators would be preferred over this method however this requires extra infra // which might not be present in the environment. type LogsCollector struct { - *baseCollector + *APICollector generations loglines.Generations writeQuit chan os.Signal lines chan *loglines.ProcessedLine slices chan *loglines.LineSlice - client *clients.Clientset sliceQuit chan os.Signal logsOutputFileName string lastPoll loglines.GenerationalLockedTime @@ -200,19 +199,16 @@ func processStream(stream io.ReadCloser, expectedEndtime time.Time) ([]*loglines } func (logs *LogsCollector) poll() error { - podName, err := logs.client.FindPodNameFromPrefix(contexts.PTPNamespace, contexts.PTPPodNamePrefix) - if err != nil { - return fmt.Errorf("failed to poll: %w", err) - } + podName := logs.ctx.GetPodName() podLogOptions := v1.PodLogOptions{ SinceTime: &metav1.Time{Time: logs.lastPoll.Time()}, - Container: contexts.PTPContainer, + Container: logs.ctx.GetContainerName(), Follow: true, Previous: false, Timestamps: true, } - podLogRequest := logs.client.K8sClient.CoreV1(). - Pods(contexts.PTPNamespace). + podLogRequest := logs.ctx.GetClientset().K8sClient.CoreV1(). + Pods(logs.ctx.GetNamespace()). GetLogs(podName, &podLogOptions). Timeout(followTimeout) stream, err := podLogRequest.Stream(context.TODO()) @@ -261,32 +257,87 @@ func (logs *LogsCollector) CleanUp() error { return nil } +//nolint:varnamelen,funlen // ok is the standard name for these checks, +func getArgsFromCollectorArgs(constructor *CollectionConstructor) ( + includeLogTimestamps bool, + logsOutputFile string, + tempDir string, + keepDebugFiles bool, + err error, +) { + logArgs, ok := constructor.CollectorArgs["Logs"] + if !ok { + return false, "", "", false, errors.New("no Logs args in collector args") + } + logsOutputFileRaw, ok := logArgs["logsOutputFile"] + if !ok { + return false, "", "", false, errors.New("no logsOutputFile in Log collector args") + } + + logsOutputFile, ok = logsOutputFileRaw.(string) + if !ok { + return false, "", "", false, errors.New("logsOutputFile is not a string") + } + + includeLogTimestampsRaw, ok := logArgs["includeLogTimestamps"] + if !ok { + return false, "", "", false, errors.New("no logsOutputFile in Log collector args") + } + + includeLogTimestamps, ok = includeLogTimestampsRaw.(bool) + if !ok { + return false, "", "", false, errors.New("logsOutputFile is not a bool") + } + + tempDirRaw, ok := logArgs["tempDir"] + if !ok { + return false, "", "", false, errors.New("no tempDir in Log collector args") + } + + tempDir, ok = tempDirRaw.(string) + if !ok { + return false, "", "", false, errors.New("tempDir is not a string") + } + + keepDebugFilesRaw, ok := logArgs["keepDebugFiles"] + if !ok { + return false, "", "", false, errors.New("no keepDebugFiles in Log collector args") + } + + keepDebugFiles, ok = keepDebugFilesRaw.(bool) + if !ok { + return false, "", "", false, errors.New("keepDebugFiles is not a string") + } + + return includeLogTimestamps, logsOutputFile, tempDir, keepDebugFiles, nil +} + // Returns a new LogsCollector from the CollectionConstuctor Factory -func NewLogsCollector(constructor *CollectionConstructor) (Collector, error) { +func NewLogsCollector(constructor *CollectionConstructor, ctx *clients.ContainerExecContext) (Collector, error) { + includeLogTimestamps, logsOutputFile, tempDir, keepDebugFiles, err := getArgsFromCollectorArgs(constructor) + if err != nil { + return &LogsCollector{}, err + } + collector := LogsCollector{ - baseCollector: newBaseCollector( + APICollector: NewAPICollector( logPollInterval, false, constructor.Callback, + ctx, ), - client: constructor.Clientset, sliceQuit: make(chan os.Signal), writeQuit: make(chan os.Signal), pruned: true, slices: make(chan *loglines.LineSlice, lineSliceChanLength), lines: make(chan *loglines.ProcessedLine, lineChanLength), lastPoll: loglines.NewGenerationalLockedTime(time.Now().Add(-time.Second)), // Stop initial since seconds from being 0 as its invalid - withTimeStamps: constructor.IncludeLogTimestamps, - logsOutputFileName: constructor.LogsOutputFile, + withTimeStamps: includeLogTimestamps, + logsOutputFileName: logsOutputFile, generations: loglines.Generations{ Store: make(map[uint32][]*loglines.LineSlice), - Dumper: loglines.NewGenerationDumper(constructor.TempDir, constructor.KeepDebugFiles), + Dumper: loglines.NewGenerationDumper(tempDir, keepDebugFiles), }, } return &collector, nil } - -func init() { - // Make log opt in as in may lose some data. - RegisterCollector(LogsCollectorName, NewLogsCollector, optional) -} diff --git a/pkg/collectors/registry.go b/collector-framework/pkg/collectors/registry.go similarity index 95% rename from pkg/collectors/registry.go rename to collector-framework/pkg/collectors/registry.go index bef2adc8..96cf1203 100644 --- a/pkg/collectors/registry.go +++ b/collector-framework/pkg/collectors/registry.go @@ -11,8 +11,8 @@ type collectonBuilderFunc func(*CollectionConstructor) (Collector, error) type collectorInclusionType int const ( - required collectorInclusionType = iota - optional + Required collectorInclusionType = iota + Optional ) type CollectorRegistry struct { @@ -34,9 +34,9 @@ func (reg *CollectorRegistry) register( ) { reg.registry[collectorName] = builderFunc switch inclusionType { - case required: + case Required: reg.required = append(reg.required, collectorName) - case optional: + case Optional: reg.optional = append(reg.optional, collectorName) default: log.Panic("Incorrect collector inclusion type") diff --git a/pkg/fetcher/builder.go b/collector-framework/pkg/fetcher/builder.go similarity index 95% rename from pkg/fetcher/builder.go rename to collector-framework/pkg/fetcher/builder.go index bce4ee59..ff616bfe 100644 --- a/pkg/fetcher/builder.go +++ b/collector-framework/pkg/fetcher/builder.go @@ -5,7 +5,7 @@ package fetcher import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) type AddCommandArgs struct { diff --git a/pkg/fetcher/fetcher.go b/collector-framework/pkg/fetcher/fetcher.go similarity index 98% rename from pkg/fetcher/fetcher.go rename to collector-framework/pkg/fetcher/fetcher.go index 9f47a4a1..b31c4b15 100644 --- a/pkg/fetcher/fetcher.go +++ b/collector-framework/pkg/fetcher/fetcher.go @@ -9,7 +9,7 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) type PostProcessFuncType func(map[string]string) (map[string]any, error) diff --git a/pkg/fetcher/unmarshal.go b/collector-framework/pkg/fetcher/unmarshal.go similarity index 100% rename from pkg/fetcher/unmarshal.go rename to collector-framework/pkg/fetcher/unmarshal.go diff --git a/pkg/fetcher/unmarshal_test.go b/collector-framework/pkg/fetcher/unmarshal_test.go similarity index 100% rename from pkg/fetcher/unmarshal_test.go rename to collector-framework/pkg/fetcher/unmarshal_test.go diff --git a/pkg/logging/logging.go b/collector-framework/pkg/logging/logging.go similarity index 93% rename from pkg/logging/logging.go rename to collector-framework/pkg/logging/logging.go index 1db41f5f..1685ffca 100644 --- a/pkg/logging/logging.go +++ b/collector-framework/pkg/logging/logging.go @@ -7,7 +7,7 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) // SetupLogging will configure the output stream and the level diff --git a/pkg/loglines/dedup.go b/collector-framework/pkg/loglines/dedup.go similarity index 98% rename from pkg/loglines/dedup.go rename to collector-framework/pkg/loglines/dedup.go index d07fd043..82778091 100644 --- a/pkg/loglines/dedup.go +++ b/collector-framework/pkg/loglines/dedup.go @@ -150,10 +150,10 @@ func DedupAB(a, b []*ProcessedLine) ([]*ProcessedLine, []*ProcessedLine) { return handleIncompleteOverlap(a, b) } - if index := findFirstIssueIndex(a[bFirstLineIndex:], b); index >= 0 { + index := findFirstIssueIndex(a[bFirstLineIndex:], b) + if index >= 0 { return handleIncompleteOverlap(a, b) } - return a[:bFirstLineIndex], b } @@ -197,7 +197,6 @@ func DedupLineSlices(lineSlices []*LineSlice) (*LineSlice, *LineSlice) { resLines := dedupedLines reference := MakeNewCombinedSlice(dedupedLines, lastLines) - for index := len(lineSlices) - 3; index >= 0; index-- { aLines, bLines := DedupAB(lineSlices[index].Lines, reference) resLines = MakeNewCombinedSlice(aLines, resLines) diff --git a/pkg/loglines/dedup_test.go b/collector-framework/pkg/loglines/dedup_test.go similarity index 90% rename from pkg/loglines/dedup_test.go rename to collector-framework/pkg/loglines/dedup_test.go index e78d9ec5..d6fa4a8f 100644 --- a/pkg/loglines/dedup_test.go +++ b/collector-framework/pkg/loglines/dedup_test.go @@ -11,7 +11,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/loglines" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/loglines" ) //nolint:unparam // its only one param for now but we might want more later @@ -130,6 +130,17 @@ var _ = Describe("Dedup AB tests", func() { Expect(dl2).To(Equal(lineSlice.Lines[:300])) }) }) + When("DedupAB is called on two line slices with second slice is overlapping but longer", func() { //nolint:dupl // don't want to dupl tests + It("should return an empty list and a complete set of the lines", func() { + lineSlice, err := loadLinesFromFile("test_files/all.log", 0) + if err != nil { + Panic() + } + dl1, dl2 := loglines.DedupAB(lineSlice.Lines[:100], lineSlice.Lines) + Expect(dl1).To(BeEmpty()) + Expect(dl2).To(Equal(lineSlice.Lines)) + }) + }) }) func TestCommand(t *testing.T) { diff --git a/pkg/loglines/lines.go b/collector-framework/pkg/loglines/lines.go similarity index 99% rename from pkg/loglines/lines.go rename to collector-framework/pkg/loglines/lines.go index 58b0a2c8..a3f3d47c 100644 --- a/pkg/loglines/lines.go +++ b/collector-framework/pkg/loglines/lines.go @@ -14,7 +14,7 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) const ( diff --git a/pkg/loglines/test_files/all.log b/collector-framework/pkg/loglines/test_files/all.log similarity index 100% rename from pkg/loglines/test_files/all.log rename to collector-framework/pkg/loglines/test_files/all.log diff --git a/pkg/runner/collector_selector.go b/collector-framework/pkg/runner/collector_selector.go similarity index 97% rename from pkg/runner/collector_selector.go rename to collector-framework/pkg/runner/collector_selector.go index 4b2e6b60..178b929d 100644 --- a/pkg/runner/collector_selector.go +++ b/collector-framework/pkg/runner/collector_selector.go @@ -7,7 +7,7 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" ) var ( @@ -16,12 +16,6 @@ var ( All string = "all" ) -func init() { - registry := collectors.GetRegistry() - OptionalCollectorNames = registry.GetOptionalNames() - RequiredCollectorNames = registry.GetRequiredNames() -} - func isIn(name string, arr []string) bool { for _, arrVal := range arr { if name == arrVal { @@ -45,6 +39,10 @@ func removeDuplicates(arr []string) []string { // collectors to be run it will enfore that required colletors // are returned func GetCollectorsToRun(selectedCollectors []string) []string { + registry := collectors.GetRegistry() + OptionalCollectorNames = registry.GetOptionalNames() + RequiredCollectorNames = registry.GetRequiredNames() + collectorNames := make([]string, 0) collectorNames = append(collectorNames, RequiredCollectorNames...) for _, name := range selectedCollectors { diff --git a/pkg/runner/runner.go b/collector-framework/pkg/runner/runner.go similarity index 92% rename from pkg/runner/runner.go rename to collector-framework/pkg/runner/runner.go index cc5d8e9a..e2cb20f1 100644 --- a/pkg/runner/runner.go +++ b/collector-framework/pkg/runner/runner.go @@ -11,10 +11,10 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) const ( @@ -62,15 +62,11 @@ func NewCollectorRunner(selectedCollectors []string) *CollectorRunner { // value in collector name, it will panic if a collector name is not known. func (runner *CollectorRunner) initialise( //nolint:funlen // allow a slightly long function callback callbacks.Callback, - ptpInterface string, clientset *clients.Clientset, pollInterval int, requestedDuration time.Duration, devInfoAnnouceInterval int, - logsOutputFile string, - includeLogTimestamps bool, - tempDir string, - keepDebugFiles bool, + collectorArgs map[string]map[string]any, ) { runner.pollInterval = pollInterval runner.endTime = time.Now().Add(requestedDuration) @@ -78,15 +74,11 @@ func (runner *CollectorRunner) initialise( //nolint:funlen // allow a slightly l constructor := &collectors.CollectionConstructor{ Callback: callback, - PTPInterface: ptpInterface, + CollectorArgs: collectorArgs, Clientset: clientset, PollInterval: pollInterval, DevInfoAnnouceInterval: devInfoAnnouceInterval, ErroredPolls: runner.erroredPolls, - LogsOutputFile: logsOutputFile, - IncludeLogTimestamps: includeLogTimestamps, - TempDir: tempDir, - KeepDebugFiles: keepDebugFiles, } registry := collectors.GetRegistry() @@ -145,7 +137,7 @@ func (runner *CollectorRunner) poller( var lastPoll time.Time pollInterval := collector.GetPollInterval() runningPolls := utils.WaitGroupCount{} - log.Debugf("Collector with poll interval %f ", pollInterval.Seconds()) + log.Debugf("Collector with poll interval %fs", pollInterval.Seconds()) for runner.shouldKeepPolling(collector) { // If pollResults were to block we do not want to keep spawning polls // so we shouldn't allow too many polls to be running simultaneously @@ -159,6 +151,7 @@ func (runner *CollectorRunner) poller( runningPolls.Wait() return default: + pollInterval = collector.GetPollInterval() log.Debug( "Collector GoRoutine:", collectorName, @@ -223,12 +216,8 @@ func (runner *CollectorRunner) Run( //nolint:funlen // allow a slightly long fun requestedDuration time.Duration, pollInterval int, devInfoAnnouceInterval int, - ptpInterface string, useAnalyserJSON bool, - logsOutputFile string, - includeLogTimestamps bool, - tempDir string, - keepDebugFiles bool, + collectorArgs map[string]map[string]any, ) { clientset, err := clients.GetClientset(kubeConfig) utils.IfErrorExitOrPanic(err) @@ -242,15 +231,11 @@ func (runner *CollectorRunner) Run( //nolint:funlen // allow a slightly long fun utils.IfErrorExitOrPanic(err) runner.initialise( callback, - ptpInterface, clientset, pollInterval, requestedDuration, devInfoAnnouceInterval, - logsOutputFile, - includeLogTimestamps, - tempDir, - keepDebugFiles, + collectorArgs, ) runner.start() diff --git a/pkg/utils/errors.go b/collector-framework/pkg/utils/errors.go similarity index 100% rename from pkg/utils/errors.go rename to collector-framework/pkg/utils/errors.go diff --git a/pkg/utils/utils.go b/collector-framework/pkg/utils/utils.go similarity index 100% rename from pkg/utils/utils.go rename to collector-framework/pkg/utils/utils.go diff --git a/collector-framework/pkg/validations/validation.go b/collector-framework/pkg/validations/validation.go new file mode 100644 index 00000000..71b06f34 --- /dev/null +++ b/collector-framework/pkg/validations/validation.go @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package validations + +import ( + "encoding/json" + "fmt" + "strings" + + "golang.org/x/mod/semver" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" +) + +type Validation interface { + Verify() error + GetID() string + GetDescription() string + GetData() any + GetOrder() int +} + +//nolint:varnamelen // id is fine this seems like a bug in varnamelen +func NewVersionCheck( + id string, + version string, + checkVersion string, + minVersion string, + description string, + order int, +) *VersionCheck { + return &VersionCheck{ + id: id, + Version: version, + checkVersion: checkVersion, + MinVersion: minVersion, + description: description, + order: order, + } +} + +type VersionCheck struct { + id string `json:"-"` + Version string `json:"version"` + checkVersion string `json:"-"` + MinVersion string `json:"expected"` + description string `json:"-"` + order int `json:"-"` +} + +func (verCheck *VersionCheck) Verify() error { + ver := fmt.Sprintf("v%s", strings.ReplaceAll(verCheck.checkVersion, "_", "-")) + if !semver.IsValid(ver) { + return fmt.Errorf("could not parse version %s", ver) + } + if semver.Compare(ver, fmt.Sprintf("v%s", verCheck.MinVersion)) < 0 { + return utils.NewInvalidEnvError( + fmt.Errorf("unexpected version: %s < %s", verCheck.checkVersion, verCheck.MinVersion), + ) + } + return nil +} + +func (verCheck *VersionCheck) GetID() string { + return verCheck.id +} + +func (verCheck *VersionCheck) GetDescription() string { + return verCheck.description +} + +func (verCheck *VersionCheck) GetData() any { //nolint:ireturn // data will vary for each validation + return verCheck +} + +func (verCheck *VersionCheck) GetOrder() int { + return verCheck.order +} + +//nolint:varnamelen // id is fine this seems like a bug in varnamelen +func NewVersionCheckWithError( + id string, + version string, + checkVersion string, + minVersion string, + description string, + order int, + err error, +) *VersionWithErrorCheck { + return &VersionWithErrorCheck{ + VersionCheck: &VersionCheck{ + id: id, + Version: version, + checkVersion: checkVersion, + MinVersion: minVersion, + description: description, + order: order, + }, + Error: err, + } +} + +type VersionWithError struct { + Error error `json:"fetchError"` + Version string `json:"version"` +} + +func MarshalVersionAndError(ver *VersionWithError) ([]byte, error) { + var err any + if ver.Error != nil { + err = ver.Error.Error() + } + marsh, marshalErr := json.Marshal(&struct { + Error any `json:"fetchError"` + Version string `json:"version"` + }{ + Version: ver.Version, + Error: err, + }) + return marsh, fmt.Errorf("failed to marshal VersionWithError %w", marshalErr) +} + +type VersionWithErrorCheck struct { + *VersionCheck + Error error +} + +func (verCheck *VersionWithErrorCheck) MarshalJSON() ([]byte, error) { + return MarshalVersionAndError(&VersionWithError{ + Version: verCheck.Version, + Error: verCheck.Error, + }) +} + +func (verCheck *VersionWithErrorCheck) Verify() error { + if verCheck.Error != nil { + return verCheck.Error + } + return verCheck.VersionCheck.Verify() +} diff --git a/testutils/fake_executor.go b/collector-framework/testutils/fake_executor.go similarity index 100% rename from testutils/fake_executor.go rename to collector-framework/testutils/fake_executor.go diff --git a/testutils/mocked_clientset.go b/collector-framework/testutils/mocked_clientset.go similarity index 96% rename from testutils/mocked_clientset.go rename to collector-framework/testutils/mocked_clientset.go index 008987c9..58dab7ea 100644 --- a/testutils/mocked_clientset.go +++ b/collector-framework/testutils/mocked_clientset.go @@ -10,7 +10,7 @@ import ( fakeK8s "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/rest" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) const kubeconfigPath string = "test_files/kubeconfig" diff --git a/go.work b/go.work new file mode 100644 index 00000000..ec35c0ae --- /dev/null +++ b/go.work @@ -0,0 +1,6 @@ +go 1.20 + +use ( + ./collector-framework + ./tgm-collector/ +) diff --git a/pkg/cmd/collect.go b/pkg/cmd/collect.go deleted file mode 100644 index 3a1babd9..00000000 --- a/pkg/cmd/collect.go +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package cmd - -import ( - "errors" - "fmt" - "os" - "os/user" - "path/filepath" - "strings" - "time" - - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/runner" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" -) - -const ( - defaultDuration string = "1000s" - defaultPollInterval int = 1 - defaultDevInfoInterval int = 60 - defaultIncludeLogTimestamps bool = false - defaultTempDir string = "." - defaultKeepDebugFiles bool = false - tempdirPerm = 0755 -) - -var ( - requestedDurationStr string - pollInterval int - devInfoAnnouceInterval int - collectorNames []string - logsOutputFile string - includeLogTimestamps bool - tempDir string - keepDebugFiles bool -) - -// collectCmd represents the collect command -var collectCmd = &cobra.Command{ - Use: "collect", - Short: "Run the collector tool", - Long: `Run the collector tool to gather data from your target cluster`, - Run: func(cmd *cobra.Command, args []string) { - collectionRunner := runner.NewCollectorRunner(collectorNames) - - requestedDuration, err := time.ParseDuration(requestedDurationStr) - if requestedDuration.Nanoseconds() < 0 { - log.Panicf("Requested duration must be positive") - } - utils.IfErrorExitOrPanic(err) - - for _, c := range collectorNames { - if (c == collectors.LogsCollectorName || c == runner.All) && logsOutputFile == "" { - utils.IfErrorExitOrPanic(utils.NewMissingInputError( - errors.New("if Logs collector is selected you must also provide a log output file")), - ) - } - } - - if strings.Contains(tempDir, "~") { - usr, err := user.Current() - if err != nil { - log.Fatal("Failed to fetch current user so could not resolve tempdir") - } - if tempDir == "~" { - tempDir = usr.HomeDir - } else if strings.HasPrefix(tempDir, "~/") { - tempDir = filepath.Join(usr.HomeDir, tempDir[2:]) - } - } - - if err := os.MkdirAll(tempDir, tempdirPerm); err != nil { - log.Fatal(err) - } - - collectionRunner.Run( - kubeConfig, - outputFile, - requestedDuration, - pollInterval, - devInfoAnnouceInterval, - ptpInterface, - useAnalyserJSON, - logsOutputFile, - includeLogTimestamps, - tempDir, - keepDebugFiles, - ) - }, -} - -func init() { //nolint:funlen // Allow this to get a little long - rootCmd.AddCommand(collectCmd) - - AddKubeconfigFlag(collectCmd) - AddOutputFlag(collectCmd) - AddFormatFlag(collectCmd) - AddInterfaceFlag(collectCmd) - - collectCmd.Flags().StringVarP( - &requestedDurationStr, - "duration", - "d", - defaultDuration, - "A positive duration string sequence of decimal numbers and a unit suffix, such as \"300ms\", \"1.5h\" or \"2h45m\"."+ - " Valid time units are \"s\", \"m\", \"h\".", - ) - collectCmd.Flags().IntVarP( - &pollInterval, - "rate", - "r", - defaultPollInterval, - "Poll interval for querying the cluster. The value will be polled once every interval. "+ - "Using --rate 10 will cause the value to be polled once every 10 seconds", - ) - collectCmd.Flags().IntVarP( - &devInfoAnnouceInterval, - "announce", - "a", - defaultDevInfoInterval, - "interval at which to emit the device info summary to the targeted output.", - ) - defaultCollectorNames := make([]string, 0) - defaultCollectorNames = append(defaultCollectorNames, runner.All) - collectCmd.Flags().StringSliceVarP( - &collectorNames, - "collector", - "s", - defaultCollectorNames, - fmt.Sprintf( - "the collectors you wish to run (case-insensitive):\n"+ - "\trequired collectors: %s (will be automatically added)\n"+ - "\toptional collectors: %s", - strings.Join(runner.RequiredCollectorNames, ", "), - strings.Join(runner.OptionalCollectorNames, ", "), - ), - ) - - collectCmd.Flags().StringVarP( - &logsOutputFile, - "logs-output", "l", "", - "Path to the logs output file. This is required when using the logs collector", - ) - collectCmd.Flags().BoolVar( - &includeLogTimestamps, - "log-timestamps", defaultIncludeLogTimestamps, - "Specifies if collected logs should include timestamps or not. (default is false)", - ) - - collectCmd.Flags().StringVarP(&tempDir, "tempdir", "t", defaultTempDir, - "Directory for storing temp/debug files. Must exist.") - collectCmd.Flags().BoolVar(&keepDebugFiles, "keep", defaultKeepDebugFiles, "Keep debug files") -} diff --git a/pkg/cmd/verifyEnv.go b/pkg/cmd/verifyEnv.go deleted file mode 100644 index ca7ecc36..00000000 --- a/pkg/cmd/verifyEnv.go +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package cmd - -import ( - "github.com/spf13/cobra" - - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/verify" -) - -var envCmd = &cobra.Command{ - Use: "env", - Short: "environment based actions", - Long: `environment based actions`, -} - -// verifyEnvCmd represents the verifyEnv command -var verifyEnvCmd = &cobra.Command{ - Use: "verify", - Short: "verify the environment is ready for collection", - Long: `verify the environment is ready for collection`, - Run: func(cmd *cobra.Command, args []string) { - verify.Verify(ptpInterface, kubeConfig, useAnalyserJSON) - }, -} - -func init() { - rootCmd.AddCommand(envCmd) - envCmd.AddCommand(verifyEnvCmd) - AddKubeconfigFlag(verifyEnvCmd) - AddOutputFlag(verifyEnvCmd) - AddFormatFlag(verifyEnvCmd) - AddInterfaceFlag(verifyEnvCmd) -} diff --git a/pkg/collectors/collector.go b/pkg/collectors/collector.go deleted file mode 100644 index d2c5b1bd..00000000 --- a/pkg/collectors/collector.go +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package collectors - -import ( - "time" - - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" -) - -type Collector interface { - Start() error // Setups any internal state required for collection to happen - Poll(chan PollResult, *utils.WaitGroupCount) // Poll for collectables - CleanUp() error // Stops the collector and cleans up any internal state. It should result in a state that can be started again - GetPollInterval() time.Duration // Returns the collectors polling interval - IsAnnouncer() bool -} - -// A union of all values required to be passed into all constructions -type CollectionConstructor struct { - Callback callbacks.Callback - Clientset *clients.Clientset - ErroredPolls chan PollResult - PTPInterface string - Msg string - LogsOutputFile string - TempDir string - PollInterval int - DevInfoAnnouceInterval int - IncludeLogTimestamps bool - KeepDebugFiles bool -} - -type PollResult struct { - CollectorName string - Errors []error -} - -type baseCollector struct { - callback callbacks.Callback - isAnnouncer bool - running bool - pollInterval time.Duration -} - -func (base *baseCollector) GetPollInterval() time.Duration { - return base.pollInterval -} - -func (base *baseCollector) IsAnnouncer() bool { - return base.isAnnouncer -} - -func (base *baseCollector) Start() error { - base.running = true - return nil -} - -func (base *baseCollector) CleanUp() error { - base.running = false - return nil -} - -func newBaseCollector( - pollInterval int, - isAnnouncer bool, - callback callbacks.Callback, -) *baseCollector { - return &baseCollector{ - callback: callback, - isAnnouncer: isAnnouncer, - running: false, - pollInterval: time.Duration(pollInterval) * time.Second, - } -} diff --git a/pkg/validations/validation.go b/pkg/validations/validation.go deleted file mode 100644 index 59a6fdd5..00000000 --- a/pkg/validations/validation.go +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package validations - -type Validation interface { - Verify() error - GetID() string - GetDescription() string - GetData() any - GetOrder() int -} diff --git a/tgm-collector/Containerfile b/tgm-collector/Containerfile new file mode 100644 index 00000000..331c2b25 --- /dev/null +++ b/tgm-collector/Containerfile @@ -0,0 +1,42 @@ +FROM registry.access.redhat.com/ubi9 AS build + +# Config +# ARGs will persist into other images, ENV vars won't. We want these to be available in both. +ENV DIR=/usr/th +ENV BIN_DIR=$DIR/bin +ENV CFG_DIR=$DIR/cfg +ENV SRC_DIR=$DIR/src + +RUN dnf -y install go make + +RUN mkdir ${DIR} && \ + mkdir ${BIN_DIR} && \ + mkdir ${CFG_DIR} && \ + mkdir ${SRC_DIR} + +ADD . ${SRC_DIR} +WORKDIR ${SRC_DIR} + +RUN make install-tools + +RUN pwd && ls +# build the test binary: outputs to ${SRC_DIR}/vse-sync-testsuite +RUN make build + +RUN cp ${SRC_DIR}/vse-sync-testsuite ${BIN_DIR}/collector-tool + +RUN dnf remove -y go make && \ + dnf clean all && \ + rm -rf ${TNF_SRC_DIR} && \ + rm -rf ${TEMP_DIR} && \ + rm -rf /root/.cache && \ + rm -rf /root/go/pkg && \ + rm -rf /root/go/src && \ + rm -rf /usr/lib/golang/pkg && \ + rm -rf /usr/lib/golang/src + + +FROM scratch +COPY --from=build / / +WORKDIR /usr/th/bin +CMD ./collector-tool diff --git a/tgm-collector/LICENSE b/tgm-collector/LICENSE new file mode 100644 index 00000000..1b04da38 --- /dev/null +++ b/tgm-collector/LICENSE @@ -0,0 +1,15 @@ +SPDX-License-Identifier: GPL-2.0-or-later + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. +. +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +. +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 51 Franklin +Street, Fifth Floor, Boston, MA 02110-1301, USA, search GPL-2.0-or-later or +see . diff --git a/tgm-collector/Makefile b/tgm-collector/Makefile new file mode 100644 index 00000000..bae2bf0d --- /dev/null +++ b/tgm-collector/Makefile @@ -0,0 +1,27 @@ +.PHONY: + install-tools + build + build-image + lint + +# Get default value of $GOBIN if not explicitly set +GO_PATH=$(shell go env GOPATH) +ifeq (,$(shell go env GOBIN)) + GOBIN=${GO_PATH}/bin +else + GOBIN=$(shell go env GOBIN) +endif + +# Install build tools and other required software. +install-tools: + go install github.com/onsi/ginkgo/v2/ginkgo + +# Build test binary +build: + PATH=${PATH}:${GOBIN} go build --race + +build-image: + podman build -t synctest:custom -f Containerfile + +lint: + golangci-lint run --timeout 5m0s --fix diff --git a/README.md b/tgm-collector/README.md similarity index 100% rename from README.md rename to tgm-collector/README.md diff --git a/tgm-collector/doc/implementing_a_collector.md b/tgm-collector/doc/implementing_a_collector.md new file mode 100644 index 00000000..26b6cce9 --- /dev/null +++ b/tgm-collector/doc/implementing_a_collector.md @@ -0,0 +1,140 @@ +# Implementing Collectors + +## High level flow +This sequance diagram shows the high level flow of data from the SUT to User and contains +```mermaid +sequenceDiagram + participant User + participant Runner + participant Collector + participant Fetcher + participant SUT + participant callback + + User ->>+ Runner: Runs binary + note left of Runner: runner.Run() + + Runner ->> Runner: Gather collectors + note right of Runner: GetCollectorsToRun() + + Runner ->> Collector: Starts collector + note over Runner,Collector: Runner.start() calls Collector.Start() + + Runner ->> Runner: Spawns Runner.Poller() goroutine for collector + loop Runner.Poller(): Until user interupts or number of polls is reached + Runner ->>+ Collector: Calls Poll + note over Runner,Collector: Runner.Poller() calls Collector.Poll() + + Collector ->>+ Fetcher: Requests Data + note over Collector,Fetcher: Collector.poll() calls function
in devices submodule which
inturn calls Fetcher.Fetch() + Fetcher ->>+ SUT: Runs commands + note left of SUT: Fetcher.Fetch() calls runCommands() + + SUT ->>- Fetcher: Command result + note left of SUT: runCommands() returns result + Fetcher ->>- Collector: Returns results + note left of Fetcher: Fetcher.Fetch() unpacks results into a struct + + + Collector ->> callback: sends data to callback + note left of callback: Callback.Call() + callback ->> User: Presents formatted data to user + Collector ->>- Runner: Sends poll sucess/failure via results channel + note left of Collector: resultsChan <- collectorsBase.PollResult{CollectorName, Errors} + + Runner ->> Runner: Reacts to failures + end + Runner ->>- Collector: Stops collector + note left of Collector: Runner.cleanUpAll() calls Collector.CleanUp() +``` + +## Step by step +You will first need to create a stuct for reporting the collected values to the user. It needs to conform to the `callbacks.OutputType` interface and any fields which you wish to show the user will require a json tag. + +Any collector must conform to the collector interface It should use the callback to expose collected information to the user. + +Once you have filled out your collector. Any arguments should be added to the `CollectionConstuctor` and function which takes the `CollectionConstuctor` should also be defined and added to the `registry`. + +An example of a very simple collector: + +In `collectors/collectors.go` any arguments additional should be added to the `CollectionConstuctor` +```go +... +type CollectionConstuctor struct { + ... + Msg string +} +... +``` + +In `collectors/announcement_collector.go` you will first need to create your reporting stuct then +you should define your collector and a constructor function which takes `CollectionConstuctor` as an argument. +```go +package collectors + +import ( + "fmt" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" +) +const ( + AnnouncementCollectorName = "MyCustomerAnouncer" + AnnouncementMsg = "custom-anouncement" +) + +// Reporting message +type AnnouncementMessage struct { + Msg string `json:"msg"` +} + +func (annMsg *AnnouncementMessage) GetAnalyserFormat() (*callbacks.AnalyserFormatType, error) { + formatted := callbacks.AnalyserFormatType{ + ID: "customAnoucner", + Data: []string{ + annMsg.Msg, + }, + } + return &formatted, nil +} + +// Collector +type AnnouncementCollector struct { + *collectorsBase.ExecCollector + msg string +} + +func (announcer *AnnouncementCollector) Poll(resultsChan chan collectorsBase.PollResult, wg *utils.WaitGroupCount) { + defer func() { + wg.Done() + }() + + msg := &AnnouncementMessage{Msg: announcer.msg} + + errs := make([]error, 0) + err := announcer.Callback.Call(&msg, AnnouncementMsg) + if err != nil { + errs = append(errs, fmt.Errorf("callback failed %w", err)) + } + resultsChan <- collectorsBase.PollResult{ + CollectorName: AnnouncementCollectorName, + Errors: errorsToReturn, + } +} + +func NewAnnouncementCollector(constuctor *CollectionConstuctor) (collectorsBase.Collector, error) { + announcer := AnnouncementCollector{ + ExecCollector: collectorsBase.NewExecCollector( + constructor.PollInterval, + false, + constructor.Callback, + ), + msg:constructor.Msg, + } + return &announcer, nil +} + +func init(){ + // We'll make this a required collector + collectorsBase.RegisterCollector(AnnouncementCollectorName, NewAnnouncementCollector, required) +} +``` diff --git a/tgm-collector/doc/implementing_a_fetcher.md b/tgm-collector/doc/implementing_a_fetcher.md new file mode 100644 index 00000000..fa21d63b --- /dev/null +++ b/tgm-collector/doc/implementing_a_fetcher.md @@ -0,0 +1,96 @@ +Fetchers a how we collect values from the cluster. +After adding commands to the fetcher when `Fetch` is called these commands are executed on the provided context. + +If we wanted to fetch the uptime we could simply add the following command + + +```go +var uptimeFetcher *Fetcher + +func init(){ + uptimeFetcher = NewFetcher() + + // "MyUptimeValue" is the key which the value be returned in the result of the fetch + // "uptime" is the command to execute + // the final parameter weither to trim whitespace from the output. + err := uptimeFetcher.AddNewCommand("MyUptimeValue", "uptime", true) + if err != nil { + panic("Failed to add uptime command to fetcher") + } +} +``` + +We need to provide a stuct to upack the data into. The field which we want to pass the value into must have a `fetcherKey` tag to allow the the fetcher to populate the field. The value of the tag must match the key in the result. + +Note: You will need defined a method `GetAnalyserFormat` [see collector documentation](implementing_a_collector.md) for clarification. + +```go +type MyUptime struct { + Raw string `fetcherKey:"MyUptimeValue"` +} + +func (uptime *MyUptime) GetAnalyserFormat() { + formatted := callbacks.AnalyserFormatType{ + ID: "MyUptimeValue", + Data: []string{ + uptime.Raw, + }, + } + return &formatted, nil +} + +func GetUptime(ctx clients.ContainerContext) (MyUptime, error) { + uptime := MyUptime{} + uptimeFetcher.Fetch(ctx, &uptime) + if err != nil { + log.Debugf("failed to fetch uptime %s", err.Error()) + return gpsNav, err + } + return uptime, nil +} +``` + +If you wish to extract/filter/transform the raw data you can define a post processing function as follows +```go +type MyUptime struct { + Raw string `fetcherKey:"MyUptimeValue"` + Uptime string `fetcherKey:"Uptime"` + Load1 string `fetcherKey:"load1"` + Load5 string `fetcherKey:"load5"` + Load15 string `fetcherKey:"load15"` +} + +var ( + uptimeFetcher *Fetcher + uptimeRegEx = regex.MustCompile( + `\d+:\d+:\d+ up (.*)` + + `,\s+\d+:\d+,\s+\d+ users,` + + `\s+load average:\s+(\d+\.?\d*), (\d+\.?\d*), (\d+\.?\d*)` + // Example 12:57:08 up 49 days, 1:46, 0 users, load average: 7.10, 9.33, 10.35 + ) +) + +func init(){ + uptimeFetcher = NewFetcher() + err := uptimeFetcher.AddNewCommand("MyUptimeValue", "uptime", true) + if err != nil { + panic("Failed to add uptime command to fetcher") + } + // Assign processUptime to uptimeFetcher. + uptimeFetcher.SetPostProcessor(processUptime) +} + +// Here we define something to take the raw result from MyUptimeValue and extracts values +func processUptime(result map[string]string) (map[string]string, error) { + processedResult := make(map[string]string) + match := uptimeRegEx.FindStringSubmatch(result["MyUptimeValue"]) + if len(match) == 0 { + return processedResult, fmt.Errorf("unable to to parse uptime output: %s", result["MyUptimeValue"]) + } + processedResult["Uptime"] = match[1] + processedResult["load1"] = match[2] + processedResult["load5"] = match[3] + processedResult["load15"] = match[4] + return processedResult, nil +} +``` diff --git a/tgm-collector/go.mod b/tgm-collector/go.mod new file mode 100644 index 00000000..89b817b4 --- /dev/null +++ b/tgm-collector/go.mod @@ -0,0 +1,71 @@ +module github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector + +go 1.18 + +require ( + github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 + github.com/icza/backscanner v0.0.0-20230330133933-bf6beb754c70 + github.com/onsi/ginkgo/v2 v2.9.0 + github.com/onsi/gomega v1.27.1 + github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework v0.0.0-00010101000000-000000000000 + github.com/sirupsen/logrus v1.9.0 + github.com/spf13/cobra v1.6.0 + golang.org/x/mod v0.8.0 + k8s.io/api v0.26.1 + k8s.io/apimachinery v0.26.1 + k8s.io/client-go v0.26.1 +) + +replace github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework => ../collector-framework + +require ( + github.com/creack/pty v1.1.17 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/moby/spdystream v0.2.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openshift/api v0.0.0-20230120195050-6ba31fa438f2 // indirect + github.com/openshift/client-go v0.0.0-20230120202327-72f107311084 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.6.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/klog/v2 v2.90.0 // indirect + k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d // indirect + k8s.io/kubectl v0.26.1 // indirect + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/go.sum b/tgm-collector/go.sum similarity index 100% rename from go.sum rename to tgm-collector/go.sum diff --git a/tgm-collector/hack/logs.go b/tgm-collector/hack/logs.go new file mode 100644 index 00000000..38179d0f --- /dev/null +++ b/tgm-collector/hack/logs.go @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package main + +import ( + "errors" + "flag" + "fmt" + "io" + "os" + "os/exec" + "path" + "regexp" + "strconv" + "strings" + "time" + + expect "github.com/Netflix/go-expect" + "github.com/icza/backscanner" + log "github.com/sirupsen/logrus" +) + +const ( + timeout = 5 * time.Second + podSafetyWait = 5 * time.Second // generous sleep so we don't create too many debug pods and break. + defaultLogWindow = 2000 * time.Second +) + +var ( + promptRE = regexp.MustCompile(`sh-4\.4#`) // line has ANSI escape characters: \r\x1b[Ksh-4.4# + logfileRE = regexp.MustCompile(`(\d)\.log(\..*)*`) +) + +var ( + kubeconfigPath string + outputPath string + tmpOutputPath string + logWindow time.Duration +) + +func check(e error) { + if e != nil { + log.Fatal(e) + } +} + +func buildDebugCommand(nodeName string) []string { + nodepath := "node/" + nodeName + return []string{"oc", "debug", "--kubeconfig", kubeconfigPath, "--quiet", nodepath} +} + +func getNodeName() string { + nodeNameCommand := []string{"get", "nodes", "--kubeconfig", kubeconfigPath, "-o=jsonpath={.items[0].metadata.name}"} + cmd := exec.Command("oc", nodeNameCommand...) + log.Debug(cmd) + var nodeName strings.Builder + cmd.Stdout = &nodeName + check(cmd.Run()) + log.Debug(nodeName.String()) + return nodeName.String() +} + +func pickLogFiles(filePaths []string) []string { + maxLogNumber := 0 + var candidateFiles []string //nolint:prealloc // performance not the goal here + for _, filePath := range filePaths { + _, fileName := path.Split(filePath) + logNumber, err := strconv.Atoi(strings.SplitN(fileName, ".", 2)[0]) //nolint:gomnd // making constant does not improve code. + if err != nil { + continue // skip file + } + if logNumber < maxLogNumber { + continue // only get files from the biggest log number + } else if logNumber > maxLogNumber { + maxLogNumber = logNumber + candidateFiles = nil + } + candidateFiles = append(candidateFiles, filePath) + } + return candidateFiles +} + +func downloadLogs(nodeName string, logPaths []string) []string { + var createdFiles []string //nolint:prealloc // performance not the goal here + var stderr strings.Builder + for _, filePath := range logPaths { + log.Infof("Getting logs from remote file: %s", filePath) + _, fileName := path.Split(filePath) + args := append(buildDebugCommand(nodeName), "--") + if strings.HasSuffix(fileName, ".gz") { + args = append(args, []string{"gzip", "-d", filePath, "--stdout"}...) + fileName = strings.ReplaceAll(fileName, ".gz", "") + } else { + args = append(args, []string{"cat", filePath}...) + } + cmd := exec.Command(args[0], args[1:]...) //nolint:gosec // accepting security risk. + + localFile := fmt.Sprintf("%s/%s", tmpOutputPath, fileName) + createdFiles = append(createdFiles, localFile) + outputFile, err := os.Create(localFile) + check(err) + cmd.Stdout = outputFile + cmd.Stderr = &stderr + + if err = cmd.Run(); err != nil { + log.Error(stderr.String()) + check(err) + } + err = outputFile.Close() + check(err) + stderr.Reset() + time.Sleep(podSafetyWait) + } + return createdFiles +} + +func getLogsFileNamesForNode(nodeName string) []string { + expecter, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(timeout)) + check(err) + defer expecter.Close() + + args := buildDebugCommand(nodeName) + cmd := exec.Command(args[0], args[1:]...) //nolint:gosec // accepting security risk. + cmd.Stdin = expecter.Tty() + cmd.Stdout = expecter.Tty() + cmd.Stderr = expecter.Tty() + + err = cmd.Start() + check(err) + defer cmd.Process.Kill() //nolint:errcheck // continue regardless of error. + + _, err = expecter.Expect(expect.Regexp(promptRE)) + check(err) + + _, err = expecter.Send("find /host/var/log/pods/openshift-ptp_linuxptp-daemon-*/linuxptp-daemon-container/*log*\n") + check(err) + logFiles, _ := expecter.Expect(expect.Regexp(promptRE)) // Just wait for timeout here as the prompt is full of invisible characters which makes regex a nightmare. + + var candidateFiles []string + for _, line := range strings.Split(logFiles, "\n") { + trimmedLine := strings.TrimSpace(line) + log.Debugf("Got Line:'%q'", trimmedLine) + if match := logfileRE.MatchString(trimmedLine); match { + candidateFiles = append(candidateFiles, trimmedLine) + } + } + logsToRetrieve := pickLogFiles(candidateFiles) + return logsToRetrieve +} + +func processLogLine(line string) (time.Time, string) { //nolint:gocritic //names not needed + splitLine := strings.SplitN(line, " ", 2) //nolint:gomnd // making constant does not improve code. + timestamp, err := time.Parse(time.RFC3339, splitLine[0]) + if err != nil { + return time.Now(), "" + } + // 2023-09-08T11:03:22.315992414+00:00 stdout F ts2phc[1374422.785]: [ts2phc.0.config] nmea sentence: GNGGA,110322.00,4233.01417,N,07112.87799,W,1,12,0.48,58.2,M,-33.0,M,, + // becomes + // ts2phc[1374422.785]: [ts2phc.0.config] nmea sentence: GNGGA,110322.00,4233.01417,N,07112.87799,W,1,12,0.48,58.2,M,-33.0,M,, + return timestamp, line[45:] +} + +func scanFileInReverseToTime(fileName string, targetTime time.Time, output *os.File) (foundTime bool) { + foundTime = false + f, err := os.Open(fileName) + check(err) + defer f.Close() + finfo, err := f.Stat() + check(err) + reverseReader := backscanner.New(f, int(finfo.Size())) + for { + line, _, err := reverseReader.Line() + if errors.Is(err, io.EOF) { + log.Infof("Finished processing file: %s", fileName) + break + } else if err != nil { + log.Errorf("Unexpected error reading file %s: %s", fileName, err) + break + } + ts, logLine := processLogLine(line) + if ts.Before(targetTime) { + foundTime = true + return + } + if line != "" { + _, _ = output.WriteString(logLine + "\n") + } + } + return +} + +func buildSingleLog(fromFiles []string, since time.Time) { + reverseFilename := fmt.Sprintf("%s/logs.gol", tmpOutputPath) + reverseFinalLogFile, err := os.Create(reverseFilename) + check(err) + defer reverseFinalLogFile.Close() + + // assuming order of fromFiles is consistent due to naming scheme: first item is most recent file, the rest are in ascending time order + reverseTimeOrder := []string{fromFiles[0]} + for i := len(fromFiles) - 1; i > 0; i-- { + reverseTimeOrder = append(reverseTimeOrder, fromFiles[i]) + } + foundTime := false + // work over files in descending time order, and lines in each file from end to start, until we find a line before since time. + for _, f := range reverseTimeOrder { + log.Infof("Processing file %s", f) + foundTime = scanFileInReverseToTime(f, since, reverseFinalLogFile) + if foundTime { + log.Infof("Found sinceTime in file %s", f) + break + } + } + if !foundTime { + log.Warn("Processed all log files without satisfying since duration") + } + + cmd := exec.Command("tac", reverseFilename) + finalLogFile, err := os.Create(outputPath) + check(err) + log.Debugf("%s > %s", cmd.Args, finalLogFile.Name()) + cmd.Stdout = finalLogFile + log.Infof("Writing final logs to %s", finalLogFile.Name()) + err = cmd.Run() + check(err) +} + +func main() { + flag.StringVar(&kubeconfigPath, "k", "", "Path to kubeconfig. Required.") + flag.StringVar(&outputPath, "o", "", "Output file for final logs. Target must exist. Required") + flag.DurationVar( + &logWindow, + "d", + defaultLogWindow, + fmt.Sprintf("Optional. Duration of logs to finally output. Defaults to %s.", defaultLogWindow), + ) + flag.StringVar( + &tmpOutputPath, + "t", + ".", + "Optional. Specify the temporary output directory. Target must exist. Defaults to working directory.", + ) + flag.Parse() + + if kubeconfigPath == "" { + log.Error("Kubeconfig path (-k) is Required") + flag.Usage() + os.Exit(1) + } + if outputPath == "" { + log.Error("Output path (-o) is Required") + flag.Usage() + os.Exit(1) + } + + sinceTime := time.Now().Add(-logWindow) + log.Infof("Getting logs since %s", sinceTime) + nodeName := getNodeName() + logFiles := getLogsFileNamesForNode(nodeName) + time.Sleep(podSafetyWait) + localFiles := downloadLogs(nodeName, logFiles) + buildSingleLog(localFiles, sinceTime) +} diff --git a/main.go b/tgm-collector/main.go similarity index 87% rename from main.go rename to tgm-collector/main.go index 2ee5ec5a..3d8d9e60 100644 --- a/main.go +++ b/tgm-collector/main.go @@ -3,7 +3,7 @@ package main import ( - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/cmd" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/cmd" ) func main() { diff --git a/tgm-collector/pkg/cmd/collect.go b/tgm-collector/pkg/cmd/collect.go new file mode 100644 index 00000000..0eeca347 --- /dev/null +++ b/tgm-collector/pkg/cmd/collect.go @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package cmd + +import ( + "errors" + "log" + "os" + "os/user" + "path/filepath" + "strings" + + fCmd "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/cmd" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/runner" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors" +) + +const ( + defaultIncludeLogTimestamps bool = false + defaultTempDir string = "." + defaultKeepDebugFiles bool = false + tempdirPerm = 0755 +) + +type CollectorArgFunc func() map[string]map[string]any + +var ( + logsOutputFile string + includeLogTimestamps bool + tempDir string + keepDebugFiles bool +) + +func init() { //nolint:funlen // Allow this to get a little long + AddInterfaceFlag(fCmd.CollectCmd) + + fCmd.CollectCmd.Flags().StringVarP( + &logsOutputFile, + "logs-output", "l", "", + "Path to the logs output file. This is required when using the logs collector", + ) + fCmd.CollectCmd.Flags().BoolVar( + &includeLogTimestamps, + "log-timestamps", defaultIncludeLogTimestamps, + "Specifies if collected logs should include timestamps or not. (default is false)", + ) + fCmd.CollectCmd.Flags().StringVarP(&tempDir, "tempdir", "t", defaultTempDir, + "Directory for storing temp/debug files. Must exist.") + fCmd.CollectCmd.Flags().BoolVar(&keepDebugFiles, "keep", defaultKeepDebugFiles, "Keep debug files") + + fCmd.SetCollecterArgsFunc(func(collectorNames []string) map[string]map[string]any { + // Check args + for _, c := range collectorNames { + if (c == collectors.LogsCollectorName || c == runner.All) && logsOutputFile == "" { + utils.IfErrorExitOrPanic(utils.NewMissingInputError( + errors.New("if Logs collector is selected you must also provide a log output file")), + ) + } + } + + if strings.Contains(tempDir, "~") { + usr, err := user.Current() + if err != nil { + log.Fatal("Failed to fetch current user so could not resolve tempdir") + } + if tempDir == "~" { + tempDir = usr.HomeDir + } else if strings.HasPrefix(tempDir, "~/") { + tempDir = filepath.Join(usr.HomeDir, tempDir[2:]) + } + } + + if err := os.MkdirAll(tempDir, tempdirPerm); err != nil { + log.Fatal(err) + } + + // Populate collector args + collectorArgs := make(map[string]map[string]any) + collectorArgs["PTP"] = map[string]any{ + "ptpInterface": ptpInterface, + } + collectorArgs["Logs"] = map[string]any{ + "logsOutputFile": logsOutputFile, + "includeLogTimestamps": includeLogTimestamps, + "tempDir": tempDir, + "keepDebugFiles": keepDebugFiles, + } + return collectorArgs + }) +} diff --git a/tgm-collector/pkg/cmd/common.go b/tgm-collector/pkg/cmd/common.go new file mode 100644 index 00000000..10190b36 --- /dev/null +++ b/tgm-collector/pkg/cmd/common.go @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package cmd + +import ( + "github.com/spf13/cobra" + + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" +) + +var ( + ptpInterface string +) + +func AddInterfaceFlag(targetCmd *cobra.Command) { + targetCmd.Flags().StringVarP(&ptpInterface, "interface", "i", "", "Name of the PTP interface") + err := targetCmd.MarkFlagRequired("interface") + utils.IfErrorExitOrPanic(err) +} diff --git a/tgm-collector/pkg/cmd/root.go b/tgm-collector/pkg/cmd/root.go new file mode 100644 index 00000000..13e26753 --- /dev/null +++ b/tgm-collector/pkg/cmd/root.go @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package cmd + +import ( + fCmd "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/cmd" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors" +) + +func Execute() { + fCmd.Execute() +} + +func init() { + collectors.IncludeCollectorsNoOp() +} diff --git a/tgm-collector/pkg/cmd/verifyEnv.go b/tgm-collector/pkg/cmd/verifyEnv.go new file mode 100644 index 00000000..b0b7805e --- /dev/null +++ b/tgm-collector/pkg/cmd/verifyEnv.go @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package cmd + +import ( + log "github.com/sirupsen/logrus" + + fCmd "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/cmd" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/verify" +) + +func init() { + AddInterfaceFlag(fCmd.VerifyEnvCmd) + fCmd.SetVerifyFunc(func(kubeconfig string, useAnalyserJSON bool) { + log.Info("Hello") + verify.Verify(ptpInterface, kubeconfig, useAnalyserJSON) + }) +} diff --git a/tgm-collector/pkg/collectors/common.go b/tgm-collector/pkg/collectors/common.go new file mode 100644 index 00000000..f2dbf842 --- /dev/null +++ b/tgm-collector/pkg/collectors/common.go @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package collectors + +import ( + "errors" + + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" +) + +//nolint:varnamelen // ok is the idomatic name for this var +func getPTPInterfaceName(constructor *collectorsBase.CollectionConstructor) (string, error) { + ptpArgs, ok := constructor.CollectorArgs["PTP"] + if !ok { + return "", errors.New("no PTP args in collector args") + } + ptpInterfaceRaw, ok := ptpArgs["ptpInterface"] + if !ok { + return "", errors.New("no ptpInterface in PTP collector args") + } + + ptpInterface, ok := ptpInterfaceRaw.(string) + if !ok { + return "", errors.New("PTP interface is not a string") + } + return ptpInterface, nil +} + +// Empty function used to insure the collectors module gets added to the resulting binary +func IncludeCollectorsNoOp() {} diff --git a/pkg/collectors/contexts/contexts.go b/tgm-collector/pkg/collectors/contexts/contexts.go similarity index 93% rename from pkg/collectors/contexts/contexts.go rename to tgm-collector/pkg/collectors/contexts/contexts.go index 8bda10ea..588fb174 100644 --- a/pkg/collectors/contexts/contexts.go +++ b/tgm-collector/pkg/collectors/contexts/contexts.go @@ -7,7 +7,7 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) const ( @@ -20,7 +20,7 @@ const ( NetlinkDebugContainerImage = "quay.io/redhat-partner-solutions/dpll-debug:0.1" ) -func GetPTPDaemonContext(clientset *clients.Clientset) (clients.ExecContext, error) { +func GetPTPDaemonContext(clientset *clients.Clientset) (*clients.ContainerExecContext, error) { ctx, err := clients.NewContainerContext(clientset, PTPNamespace, PTPPodNamePrefix, PTPContainer) if err != nil { return ctx, fmt.Errorf("could not create container context %w", err) diff --git a/pkg/collectors/dev_info_collector.go b/tgm-collector/pkg/collectors/dev_info_collector.go similarity index 73% rename from pkg/collectors/dev_info_collector.go rename to tgm-collector/pkg/collectors/dev_info_collector.go index f3210d63..12c88294 100644 --- a/pkg/collectors/dev_info_collector.go +++ b/tgm-collector/pkg/collectors/dev_info_collector.go @@ -11,19 +11,19 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/validations" + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + validationsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/validations" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/validations" ) type DevInfoCollector struct { - *baseCollector - ctx clients.ExecContext + *collectorsBase.ExecCollector devInfo *devices.PTPDeviceInfo quit chan os.Signal - erroredPolls chan PollResult + erroredPolls chan collectorsBase.PollResult requiresFetch chan bool interfaceName string wg sync.WaitGroup @@ -36,7 +36,10 @@ const ( // Start sets up the collector so it is ready to be polled func (ptpDev *DevInfoCollector) Start() error { - ptpDev.running = true + err := ptpDev.ExecCollector.Start() + if err != nil { + return fmt.Errorf("failed to start dev info collector: %w", err) + } go ptpDev.monitorErroredPolls() return nil } @@ -74,7 +77,7 @@ func (ptpDev *DevInfoCollector) poll() error { var devInfo *devices.PTPDeviceInfo select { case <-ptpDev.requiresFetch: - fetchedDevInfo, err := devices.GetPTPDeviceInfo(ptpDev.interfaceName, ptpDev.ctx) + fetchedDevInfo, err := devices.GetPTPDeviceInfo(ptpDev.interfaceName, ptpDev.GetContext()) if err != nil { return fmt.Errorf("failed to fetch %s %w", DeviceInfo, err) } @@ -84,7 +87,7 @@ func (ptpDev *DevInfoCollector) poll() error { devInfo = ptpDev.devInfo } - err := ptpDev.callback.Call(devInfo, DeviceInfo) + err := ptpDev.Callback.Call(devInfo, DeviceInfo) if err != nil { return fmt.Errorf("callback failed %w", err) } @@ -93,7 +96,7 @@ func (ptpDev *DevInfoCollector) poll() error { // Poll collects information from the cluster then // calls the callback.Call to allow that to persist it -func (ptpDev *DevInfoCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { +func (ptpDev *DevInfoCollector) Poll(resultsChan chan collectorsBase.PollResult, wg *utils.WaitGroupCount) { defer func() { wg.Done() }() @@ -102,7 +105,7 @@ func (ptpDev *DevInfoCollector) Poll(resultsChan chan PollResult, wg *utils.Wait if err != nil { errorsToReturn = append(errorsToReturn, err) } - resultsChan <- PollResult{ + resultsChan <- collectorsBase.PollResult{ CollectorName: DPLLCollectorName, Errors: errorsToReturn, } @@ -110,15 +113,18 @@ func (ptpDev *DevInfoCollector) Poll(resultsChan chan PollResult, wg *utils.Wait // CleanUp stops a running collector func (ptpDev *DevInfoCollector) CleanUp() error { - ptpDev.running = false + err := ptpDev.ExecCollector.CleanUp() + if err != nil { + return fmt.Errorf("failed to cleanly stop ptp dev info collector: %w", err) + } ptpDev.quit <- os.Kill ptpDev.wg.Wait() return nil } -func verify(ptpDevInfo *devices.PTPDeviceInfo, constructor *CollectionConstructor) error { +func verify(ptpDevInfo *devices.PTPDeviceInfo, constructor *collectorsBase.CollectionConstructor) error { checkErrors := make([]error, 0) - checks := []validations.Validation{ + checks := []validationsBase.Validation{ validations.NewDeviceDetails(ptpDevInfo), validations.NewDeviceDriver(ptpDevInfo), validations.NewDeviceFirmware(ptpDevInfo), @@ -149,18 +155,24 @@ func verify(ptpDevInfo *devices.PTPDeviceInfo, constructor *CollectionConstructo } // Returns a new DevInfoCollector from the CollectionConstuctor Factory -func NewDevInfoCollector(constructor *CollectionConstructor) (Collector, error) { +func NewDevInfoCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { // Build DPPInfoFetcher ahead of time call to GetPTPDeviceInfo will build the other ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) if err != nil { return &DevInfoCollector{}, fmt.Errorf("failed to create DevInfoCollector: %w", err) } - err = devices.BuildPTPDeviceInfo(constructor.PTPInterface) + + ptpInterface, err := getPTPInterfaceName(constructor) + if err != nil { + return &DevInfoCollector{}, err + } + + err = devices.BuildPTPDeviceInfo(ptpInterface) if err != nil { return &DevInfoCollector{}, fmt.Errorf("failed to build fetcher for PTPDeviceInfo %w", err) } - ptpDevInfo, err := devices.GetPTPDeviceInfo(constructor.PTPInterface, ctx) + ptpDevInfo, err := devices.GetPTPDeviceInfo(ptpInterface, ctx) if err != nil { return &DevInfoCollector{}, fmt.Errorf("failed to fetch initial DeviceInfo %w", err) } @@ -171,13 +183,13 @@ func NewDevInfoCollector(constructor *CollectionConstructor) (Collector, error) } collector := DevInfoCollector{ - baseCollector: newBaseCollector( + ExecCollector: collectorsBase.NewExecCollector( constructor.DevInfoAnnouceInterval, true, constructor.Callback, + ctx, ), - ctx: ctx, - interfaceName: constructor.PTPInterface, + interfaceName: ptpInterface, devInfo: &ptpDevInfo, quit: make(chan os.Signal), erroredPolls: constructor.ErroredPolls, @@ -188,5 +200,5 @@ func NewDevInfoCollector(constructor *CollectionConstructor) (Collector, error) } func init() { - RegisterCollector(DevInfoCollectorName, NewDevInfoCollector, required) + collectorsBase.RegisterCollector(DevInfoCollectorName, NewDevInfoCollector, collectorsBase.Required) } diff --git a/pkg/collectors/devices/common.go b/tgm-collector/pkg/collectors/devices/common.go similarity index 92% rename from pkg/collectors/devices/common.go rename to tgm-collector/pkg/collectors/devices/common.go index 42009e50..2d9a12da 100644 --- a/pkg/collectors/devices/common.go +++ b/tgm-collector/pkg/collectors/devices/common.go @@ -7,8 +7,8 @@ import ( "strings" "time" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) var dateCmd *clients.Cmd diff --git a/pkg/collectors/devices/device_info.go b/tgm-collector/pkg/collectors/devices/device_info.go similarity index 98% rename from pkg/collectors/devices/device_info.go rename to tgm-collector/pkg/collectors/devices/device_info.go index 9ffbf96c..273738f2 100644 --- a/pkg/collectors/devices/device_info.go +++ b/tgm-collector/pkg/collectors/devices/device_info.go @@ -11,9 +11,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/fetcher" ) type PTPDeviceInfo struct { diff --git a/pkg/collectors/devices/device_info_test.go b/tgm-collector/pkg/collectors/devices/device_info_test.go similarity index 97% rename from pkg/collectors/devices/device_info_test.go rename to tgm-collector/pkg/collectors/devices/device_info_test.go index 16dbbe71..9bf49323 100644 --- a/pkg/collectors/devices/device_info_test.go +++ b/tgm-collector/pkg/collectors/devices/device_info_test.go @@ -15,9 +15,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/remotecommand" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ethtoolOutput = ` diff --git a/pkg/collectors/devices/doc.go b/tgm-collector/pkg/collectors/devices/doc.go similarity index 100% rename from pkg/collectors/devices/doc.go rename to tgm-collector/pkg/collectors/devices/doc.go diff --git a/pkg/collectors/devices/dpll_fs.go b/tgm-collector/pkg/collectors/devices/dpll_fs.go similarity index 97% rename from pkg/collectors/devices/dpll_fs.go rename to tgm-collector/pkg/collectors/devices/dpll_fs.go index 4c7695dd..967943c1 100644 --- a/pkg/collectors/devices/dpll_fs.go +++ b/tgm-collector/pkg/collectors/devices/dpll_fs.go @@ -10,9 +10,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/fetcher" ) const ( diff --git a/pkg/collectors/devices/dpll_fs_test.go b/tgm-collector/pkg/collectors/devices/dpll_fs_test.go similarity index 96% rename from pkg/collectors/devices/dpll_fs_test.go rename to tgm-collector/pkg/collectors/devices/dpll_fs_test.go index 9215a72e..d69a6398 100644 --- a/pkg/collectors/devices/dpll_fs_test.go +++ b/tgm-collector/pkg/collectors/devices/dpll_fs_test.go @@ -12,9 +12,9 @@ import ( "k8s.io/client-go/tools/remotecommand" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) var _ = Describe("NewContainerContext", func() { diff --git a/pkg/collectors/devices/dpll_netlink.go b/tgm-collector/pkg/collectors/devices/dpll_netlink.go similarity index 98% rename from pkg/collectors/devices/dpll_netlink.go rename to tgm-collector/pkg/collectors/devices/dpll_netlink.go index 7d4675d8..a0170a2e 100644 --- a/pkg/collectors/devices/dpll_netlink.go +++ b/tgm-collector/pkg/collectors/devices/dpll_netlink.go @@ -11,9 +11,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/fetcher" ) var states = map[string]string{ diff --git a/pkg/collectors/devices/gps_ubx.go b/tgm-collector/pkg/collectors/devices/gps_ubx.go similarity index 98% rename from pkg/collectors/devices/gps_ubx.go rename to tgm-collector/pkg/collectors/devices/gps_ubx.go index 6e47d247..88990d1c 100644 --- a/pkg/collectors/devices/gps_ubx.go +++ b/tgm-collector/pkg/collectors/devices/gps_ubx.go @@ -10,10 +10,10 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/fetcher" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) type GPSDetails struct { diff --git a/pkg/collectors/devices/gps_ubx_test.go b/tgm-collector/pkg/collectors/devices/gps_ubx_test.go similarity index 96% rename from pkg/collectors/devices/gps_ubx_test.go rename to tgm-collector/pkg/collectors/devices/gps_ubx_test.go index 547c7f8a..2c73e9cb 100644 --- a/pkg/collectors/devices/gps_ubx_test.go +++ b/tgm-collector/pkg/collectors/devices/gps_ubx_test.go @@ -12,9 +12,9 @@ import ( "k8s.io/client-go/tools/remotecommand" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) var _ = Describe("GetGPSNav", func() { diff --git a/pkg/collectors/devices/gps_ubx_ver.go b/tgm-collector/pkg/collectors/devices/gps_ubx_ver.go similarity index 97% rename from pkg/collectors/devices/gps_ubx_ver.go rename to tgm-collector/pkg/collectors/devices/gps_ubx_ver.go index 0dfda78c..3571a24c 100644 --- a/pkg/collectors/devices/gps_ubx_ver.go +++ b/tgm-collector/pkg/collectors/devices/gps_ubx_ver.go @@ -10,10 +10,10 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/fetcher" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) type GPSVersions struct { diff --git a/pkg/collectors/devices/gps_ubx_ver_test.go b/tgm-collector/pkg/collectors/devices/gps_ubx_ver_test.go similarity index 96% rename from pkg/collectors/devices/gps_ubx_ver_test.go rename to tgm-collector/pkg/collectors/devices/gps_ubx_ver_test.go index 913712d1..87e6eff3 100644 --- a/pkg/collectors/devices/gps_ubx_ver_test.go +++ b/tgm-collector/pkg/collectors/devices/gps_ubx_ver_test.go @@ -12,9 +12,9 @@ import ( "k8s.io/client-go/tools/remotecommand" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) var _ = Describe("GetGPSNav", func() { diff --git a/pkg/collectors/devices/pmc.go b/tgm-collector/pkg/collectors/devices/pmc.go similarity index 98% rename from pkg/collectors/devices/pmc.go rename to tgm-collector/pkg/collectors/devices/pmc.go index f83e9336..4c398635 100644 --- a/pkg/collectors/devices/pmc.go +++ b/tgm-collector/pkg/collectors/devices/pmc.go @@ -9,9 +9,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/fetcher" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/fetcher" ) type PMCInfo struct { diff --git a/pkg/collectors/devices/pmc_test.go b/tgm-collector/pkg/collectors/devices/pmc_test.go similarity index 96% rename from pkg/collectors/devices/pmc_test.go rename to tgm-collector/pkg/collectors/devices/pmc_test.go index 516b759f..09c1a236 100644 --- a/pkg/collectors/devices/pmc_test.go +++ b/tgm-collector/pkg/collectors/devices/pmc_test.go @@ -12,9 +12,9 @@ import ( "k8s.io/client-go/tools/remotecommand" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/testutils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) var _ = Describe("GetPMC", func() { diff --git a/pkg/collectors/devices/test_files/kubeconfig b/tgm-collector/pkg/collectors/devices/test_files/kubeconfig similarity index 100% rename from pkg/collectors/devices/test_files/kubeconfig rename to tgm-collector/pkg/collectors/devices/test_files/kubeconfig diff --git a/pkg/collectors/dpll_collector.go b/tgm-collector/pkg/collectors/dpll_collector.go similarity index 55% rename from pkg/collectors/dpll_collector.go rename to tgm-collector/pkg/collectors/dpll_collector.go index 1503ea44..c663e035 100644 --- a/pkg/collectors/dpll_collector.go +++ b/tgm-collector/pkg/collectors/dpll_collector.go @@ -7,8 +7,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( @@ -16,12 +17,16 @@ const ( ) // Returns a new DPLLCollector from the CollectionConstuctor Factory -func NewDPLLCollector(constructor *CollectionConstructor) (Collector, error) { +func NewDPLLCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) if err != nil { return &DPLLNetlinkCollector{}, fmt.Errorf("failed to create DPLLCollector: %w", err) } - dpllFSExists, err := devices.IsDPLLFileSystemPresent(ctx, constructor.PTPInterface) + ptpInterface, err := getPTPInterfaceName(constructor) + if err != nil { + return &DPLLNetlinkCollector{}, err + } + dpllFSExists, err := devices.IsDPLLFileSystemPresent(ctx, ptpInterface) log.Debug("DPLL FS exists: ", dpllFSExists) if dpllFSExists && err == nil { return NewDPLLFilesystemCollector(constructor) @@ -31,5 +36,5 @@ func NewDPLLCollector(constructor *CollectionConstructor) (Collector, error) { } func init() { - RegisterCollector(DPLLCollectorName, NewDPLLCollector, optional) + collectorsBase.RegisterCollector(DPLLCollectorName, NewDPLLCollector, collectorsBase.Optional) } diff --git a/pkg/collectors/dpll_collector_fs.go b/tgm-collector/pkg/collectors/dpll_collector_fs.go similarity index 61% rename from pkg/collectors/dpll_collector_fs.go rename to tgm-collector/pkg/collectors/dpll_collector_fs.go index c36d83ec..4aa86f39 100644 --- a/pkg/collectors/dpll_collector_fs.go +++ b/tgm-collector/pkg/collectors/dpll_collector_fs.go @@ -5,15 +5,14 @@ package collectors import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) type DPLLFilesystemCollector struct { - *baseCollector - ctx clients.ExecContext + *collectorsBase.ExecCollector interfaceName string } @@ -22,20 +21,14 @@ const ( DPLLInfo = "dpll-info-fs" ) -// Start sets up the collector so it is ready to be polled -func (dpll *DPLLFilesystemCollector) Start() error { - dpll.running = true - return nil -} - // polls for the dpll info then passes it to the callback func (dpll *DPLLFilesystemCollector) poll() error { - dpllInfo, err := devices.GetDevDPLLFilesystemInfo(dpll.ctx, dpll.interfaceName) + dpllInfo, err := devices.GetDevDPLLFilesystemInfo(dpll.GetContext(), dpll.interfaceName) if err != nil { return fmt.Errorf("failed to fetch %s %w", DPLLInfo, err) } - err = dpll.callback.Call(&dpllInfo, DPLLInfo) + err = dpll.Callback.Call(&dpllInfo, DPLLInfo) if err != nil { return fmt.Errorf("callback failed %w", err) } @@ -44,7 +37,7 @@ func (dpll *DPLLFilesystemCollector) poll() error { // Poll collects information from the cluster then // calls the callback.Call to allow that to persist it -func (dpll *DPLLFilesystemCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { +func (dpll *DPLLFilesystemCollector) Poll(resultsChan chan collectorsBase.PollResult, wg *utils.WaitGroupCount) { defer func() { wg.Done() }() @@ -53,37 +46,35 @@ func (dpll *DPLLFilesystemCollector) Poll(resultsChan chan PollResult, wg *utils if err != nil { errorsToReturn = append(errorsToReturn, err) } - resultsChan <- PollResult{ + resultsChan <- collectorsBase.PollResult{ CollectorName: DPLLFilesystemCollectorName, Errors: errorsToReturn, } } -// CleanUp stops a running collector -func (dpll *DPLLFilesystemCollector) CleanUp() error { - dpll.running = false - return nil -} - // Returns a new DPLLFilesystemCollector from the CollectionConstuctor Factory -func NewDPLLFilesystemCollector(constructor *CollectionConstructor) (Collector, error) { +func NewDPLLFilesystemCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) if err != nil { return &DPLLFilesystemCollector{}, fmt.Errorf("failed to create DPLLFilesystemCollector: %w", err) } - err = devices.BuildFilesystemDPLLInfoFetcher(constructor.PTPInterface) + ptpInterface, err := getPTPInterfaceName(constructor) + if err != nil { + return &DPLLFilesystemCollector{}, err + } + err = devices.BuildFilesystemDPLLInfoFetcher(ptpInterface) if err != nil { return &DPLLFilesystemCollector{}, fmt.Errorf("failed to build fetcher for DPLLInfo %w", err) } collector := DPLLFilesystemCollector{ - baseCollector: newBaseCollector( + ExecCollector: collectorsBase.NewExecCollector( constructor.PollInterval, false, constructor.Callback, + ctx, ), - interfaceName: constructor.PTPInterface, - ctx: ctx, + interfaceName: ptpInterface, } return &collector, nil } diff --git a/pkg/collectors/dpll_collector_netlink.go b/tgm-collector/pkg/collectors/dpll_collector_netlink.go similarity index 59% rename from pkg/collectors/dpll_collector_netlink.go rename to tgm-collector/pkg/collectors/dpll_collector_netlink.go index d53b9c92..f49c4a8f 100644 --- a/pkg/collectors/dpll_collector_netlink.go +++ b/tgm-collector/pkg/collectors/dpll_collector_netlink.go @@ -7,15 +7,15 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) type DPLLNetlinkCollector struct { - *baseCollector - ctx *clients.ContainerCreationExecContext + *collectorsBase.ExecCollector interfaceName string clockID int64 } @@ -27,14 +27,23 @@ const ( // Start sets up the collector so it is ready to be polled func (dpll *DPLLNetlinkCollector) Start() error { - dpll.running = true - err := dpll.ctx.CreatePodAndWait() + err := dpll.ExecCollector.Start() + if err != nil { + return fmt.Errorf("failed to start dpll netlink collector: %w", err) + } + + ctx, ok := dpll.GetContext().(*clients.ContainerCreationExecContext) + if !ok { + return fmt.Errorf("dpll netlink collector has an incorrect context type") + } + + err = ctx.CreatePodAndWait() if err != nil { return fmt.Errorf("dpll netlink collector failed to start pod: %w", err) } log.Debug("dpll.interfaceName: ", dpll.interfaceName) - log.Debug("dpll.ctx: ", dpll.ctx) - clockIDStuct, err := devices.GetClockID(dpll.ctx, dpll.interfaceName) + log.Debug("dpll.ctx: ", ctx) + clockIDStuct, err := devices.GetClockID(ctx, dpll.interfaceName) if err != nil { return fmt.Errorf("dpll netlink collector failed to find clock id: %w", err) } @@ -49,12 +58,12 @@ func (dpll *DPLLNetlinkCollector) Start() error { // polls for the dpll info then passes it to the callback func (dpll *DPLLNetlinkCollector) poll() error { - dpllInfo, err := devices.GetDevDPLLNetlinkInfo(dpll.ctx, dpll.clockID) + dpllInfo, err := devices.GetDevDPLLNetlinkInfo(dpll.GetContext(), dpll.clockID) if err != nil { return fmt.Errorf("failed to fetch %s %w", DPLLNetlinkInfo, err) } - err = dpll.callback.Call(&dpllInfo, DPLLNetlinkInfo) + err = dpll.Callback.Call(&dpllInfo, DPLLNetlinkInfo) if err != nil { return fmt.Errorf("callback failed %w", err) } @@ -63,7 +72,7 @@ func (dpll *DPLLNetlinkCollector) poll() error { // Poll collects information from the cluster then // calls the callback.Call to allow that to persist it -func (dpll *DPLLNetlinkCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { +func (dpll *DPLLNetlinkCollector) Poll(resultsChan chan collectorsBase.PollResult, wg *utils.WaitGroupCount) { defer func() { wg.Done() }() @@ -72,7 +81,7 @@ func (dpll *DPLLNetlinkCollector) Poll(resultsChan chan PollResult, wg *utils.Wa if err != nil { errorsToReturn = append(errorsToReturn, err) } - resultsChan <- PollResult{ + resultsChan <- collectorsBase.PollResult{ CollectorName: DPLLNetlinkCollectorName, Errors: errorsToReturn, } @@ -80,8 +89,17 @@ func (dpll *DPLLNetlinkCollector) Poll(resultsChan chan PollResult, wg *utils.Wa // CleanUp stops a running collector func (dpll *DPLLNetlinkCollector) CleanUp() error { - dpll.running = false - err := dpll.ctx.DeletePodAndWait() + err := dpll.ExecCollector.CleanUp() + if err != nil { + return fmt.Errorf("failed to cleanly stop dpll collector: %w", err) + } + + ctx, ok := dpll.GetContext().(*clients.ContainerCreationExecContext) + if !ok { + return fmt.Errorf("dpll netlink collector has an incorrect context type") + } + + err = ctx.DeletePodAndWait() if err != nil { return fmt.Errorf("dpll netlink collector failed to clean up: %w", err) } @@ -89,20 +107,24 @@ func (dpll *DPLLNetlinkCollector) CleanUp() error { } // Returns a new DPLLNetlinkCollector from the CollectionConstuctor Factory -func NewDPLLNetlinkCollector(constructor *CollectionConstructor) (Collector, error) { +func NewDPLLNetlinkCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { ctx, err := contexts.GetNetlinkContext(constructor.Clientset) if err != nil { return &DPLLNetlinkCollector{}, fmt.Errorf("failed to create DPLLNetlinkCollector: %w", err) } + ptpInterface, err := getPTPInterfaceName(constructor) + if err != nil { + return &DPLLNetlinkCollector{}, err + } collector := DPLLNetlinkCollector{ - baseCollector: newBaseCollector( + ExecCollector: collectorsBase.NewExecCollector( constructor.PollInterval, false, constructor.Callback, + ctx, ), - interfaceName: constructor.PTPInterface, - ctx: ctx, + interfaceName: ptpInterface, } return &collector, nil diff --git a/pkg/collectors/gps_ubx_collector.go b/tgm-collector/pkg/collectors/gps_ubx_collector.go similarity index 60% rename from pkg/collectors/gps_ubx_collector.go rename to tgm-collector/pkg/collectors/gps_ubx_collector.go index 8086dbc1..51e33399 100644 --- a/pkg/collectors/gps_ubx_collector.go +++ b/tgm-collector/pkg/collectors/gps_ubx_collector.go @@ -5,10 +5,10 @@ package collectors //nolint:dupl // new collector import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) var ( @@ -17,17 +17,16 @@ var ( ) type GPSCollector struct { - *baseCollector - ctx clients.ExecContext + *collectorsBase.ExecCollector interfaceName string } func (gps *GPSCollector) poll() error { - gpsNav, err := devices.GetGPSNav(gps.ctx) + gpsNav, err := devices.GetGPSNav(gps.GetContext()) if err != nil { return fmt.Errorf("failed to fetch %s %w", gpsNavKey, err) } - err = gps.callback.Call(&gpsNav, gpsNavKey) + err = gps.Callback.Call(&gpsNav, gpsNavKey) if err != nil { return fmt.Errorf("callback failed %w", err) } @@ -36,7 +35,7 @@ func (gps *GPSCollector) poll() error { // Poll collects information from the cluster then // calls the callback.Call to allow that to persist it -func (gps *GPSCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { +func (gps *GPSCollector) Poll(resultsChan chan collectorsBase.PollResult, wg *utils.WaitGroupCount) { defer func() { wg.Done() }() @@ -46,32 +45,35 @@ func (gps *GPSCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCo if err != nil { errorsToReturn = append(errorsToReturn, err) } - resultsChan <- PollResult{ + resultsChan <- collectorsBase.PollResult{ CollectorName: GPSCollectorName, Errors: errorsToReturn, } } // Returns a new GPSCollector based on values in the CollectionConstructor -func NewGPSCollector(constructor *CollectionConstructor) (Collector, error) { +func NewGPSCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) if err != nil { return &GPSCollector{}, fmt.Errorf("failed to create DPLLCollector: %w", err) } - + ptpInterface, err := getPTPInterfaceName(constructor) + if err != nil { + return &GPSCollector{}, err + } collector := GPSCollector{ - baseCollector: newBaseCollector( + ExecCollector: collectorsBase.NewExecCollector( constructor.PollInterval, false, constructor.Callback, + ctx, ), - ctx: ctx, - interfaceName: constructor.PTPInterface, + interfaceName: ptpInterface, } return &collector, nil } func init() { - RegisterCollector(GPSCollectorName, NewGPSCollector, optional) + collectorsBase.RegisterCollector(GPSCollectorName, NewGPSCollector, collectorsBase.Optional) } diff --git a/tgm-collector/pkg/collectors/log_follower.go b/tgm-collector/pkg/collectors/log_follower.go new file mode 100644 index 00000000..92ff646b --- /dev/null +++ b/tgm-collector/pkg/collectors/log_follower.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package collectors + +import ( + "fmt" + + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" +) + +var LogsCollectorName = collectorsBase.LogsCollectorName + +func NewPTPLogsCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { + ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) + if err != nil { + return &collectorsBase.LogsCollector{}, fmt.Errorf("failed to create DPLLCollector: %w", err) + } + logCollector, err := collectorsBase.NewLogsCollector(constructor, ctx) + if err != nil { + err = fmt.Errorf("failed to create ptp log collector: %w", err) + } + return logCollector, err +} + +func init() { + // Make log opt in as in may lose some data. + collectorsBase.RegisterCollector(LogsCollectorName, NewPTPLogsCollector, collectorsBase.Optional) +} diff --git a/pkg/collectors/pmc_collector.go b/tgm-collector/pkg/collectors/pmc_collector.go similarity index 63% rename from pkg/collectors/pmc_collector.go rename to tgm-collector/pkg/collectors/pmc_collector.go index e9e33c10..6c2c0ab4 100644 --- a/pkg/collectors/pmc_collector.go +++ b/tgm-collector/pkg/collectors/pmc_collector.go @@ -5,10 +5,10 @@ package collectors //nolint:dupl // new collector import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + collectorsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/collectors" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( @@ -17,16 +17,15 @@ const ( ) type PMCCollector struct { - *baseCollector - ctx clients.ExecContext + *collectorsBase.ExecCollector } func (pmc *PMCCollector) poll() error { - gmSetting, err := devices.GetPMC(pmc.ctx) + gmSetting, err := devices.GetPMC(pmc.GetContext()) if err != nil { return fmt.Errorf("failed to fetch %s %w", PMCInfo, err) } - err = pmc.callback.Call(&gmSetting, PMCInfo) + err = pmc.Callback.Call(&gmSetting, PMCInfo) if err != nil { return fmt.Errorf("callback failed %w", err) } @@ -35,7 +34,7 @@ func (pmc *PMCCollector) poll() error { // Poll collects information from the cluster then // calls the callback.Call to allow that to persist it -func (pmc *PMCCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCount) { +func (pmc *PMCCollector) Poll(resultsChan chan collectorsBase.PollResult, wg *utils.WaitGroupCount) { defer func() { wg.Done() }() @@ -45,31 +44,31 @@ func (pmc *PMCCollector) Poll(resultsChan chan PollResult, wg *utils.WaitGroupCo if err != nil { errorsToReturn = append(errorsToReturn, err) } - resultsChan <- PollResult{ + resultsChan <- collectorsBase.PollResult{ CollectorName: PMCCollectorName, Errors: errorsToReturn, } } // Returns a new PMCCollector based on values in the CollectionConstructor -func NewPMCCollector(constructor *CollectionConstructor) (Collector, error) { +func NewPMCCollector(constructor *collectorsBase.CollectionConstructor) (collectorsBase.Collector, error) { ctx, err := contexts.GetPTPDaemonContext(constructor.Clientset) if err != nil { return &PMCCollector{}, fmt.Errorf("failed to create PMCCollector: %w", err) } collector := PMCCollector{ - baseCollector: newBaseCollector( + ExecCollector: collectorsBase.NewExecCollector( constructor.PollInterval, false, constructor.Callback, + ctx, ), - ctx: ctx, } return &collector, nil } func init() { - RegisterCollector(PMCCollectorName, NewPMCCollector, optional) + collectorsBase.RegisterCollector(PMCCollectorName, NewPMCCollector, collectorsBase.Optional) } diff --git a/pkg/validations/cluster_version.go b/tgm-collector/pkg/validations/cluster_version.go similarity index 98% rename from pkg/validations/cluster_version.go rename to tgm-collector/pkg/validations/cluster_version.go index c2b6d43a..8b71aa7b 100644 --- a/pkg/validations/cluster_version.go +++ b/tgm-collector/pkg/validations/cluster_version.go @@ -13,7 +13,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) const ( diff --git a/pkg/validations/common.go b/tgm-collector/pkg/validations/common.go similarity index 98% rename from pkg/validations/common.go rename to tgm-collector/pkg/validations/common.go index 747f04aa..ec9ebcc2 100644 --- a/pkg/validations/common.go +++ b/tgm-collector/pkg/validations/common.go @@ -9,7 +9,7 @@ import ( "golang.org/x/mod/semver" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) const ( diff --git a/pkg/validations/device.go b/tgm-collector/pkg/validations/device.go similarity index 94% rename from pkg/validations/device.go rename to tgm-collector/pkg/validations/device.go index 2fe54e2a..2ee9f641 100644 --- a/pkg/validations/device.go +++ b/tgm-collector/pkg/validations/device.go @@ -5,8 +5,8 @@ package validations import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/device_driver.go b/tgm-collector/pkg/validations/device_driver.go similarity index 97% rename from pkg/validations/device_driver.go rename to tgm-collector/pkg/validations/device_driver.go index 7bdcafe0..c3d41e5a 100644 --- a/pkg/validations/device_driver.go +++ b/tgm-collector/pkg/validations/device_driver.go @@ -8,7 +8,7 @@ import ( "golang.org/x/mod/semver" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/device_firmware.go b/tgm-collector/pkg/validations/device_firmware.go similarity index 94% rename from pkg/validations/device_firmware.go rename to tgm-collector/pkg/validations/device_firmware.go index 7f399426..a21ef08b 100644 --- a/pkg/validations/device_firmware.go +++ b/tgm-collector/pkg/validations/device_firmware.go @@ -5,7 +5,7 @@ package validations import ( "strings" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gnss_ant_power_status.go b/tgm-collector/pkg/validations/gnss_ant_power_status.go similarity index 94% rename from pkg/validations/gnss_ant_power_status.go rename to tgm-collector/pkg/validations/gnss_ant_power_status.go index d64f63c0..21c649e1 100644 --- a/pkg/validations/gnss_ant_power_status.go +++ b/tgm-collector/pkg/validations/gnss_ant_power_status.go @@ -5,8 +5,8 @@ package validations import ( "errors" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gnss_devices.go b/tgm-collector/pkg/validations/gnss_devices.go similarity index 93% rename from pkg/validations/gnss_devices.go rename to tgm-collector/pkg/validations/gnss_devices.go index 0c9b4566..843bd4c4 100644 --- a/pkg/validations/gnss_devices.go +++ b/tgm-collector/pkg/validations/gnss_devices.go @@ -5,8 +5,8 @@ package validations import ( "errors" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gnss_firmware_version.go b/tgm-collector/pkg/validations/gnss_firmware_version.go similarity index 94% rename from pkg/validations/gnss_firmware_version.go rename to tgm-collector/pkg/validations/gnss_firmware_version.go index cdaa9e37..2cfda729 100644 --- a/pkg/validations/gnss_firmware_version.go +++ b/tgm-collector/pkg/validations/gnss_firmware_version.go @@ -5,7 +5,7 @@ package validations import ( "strings" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gnss_module.go b/tgm-collector/pkg/validations/gnss_module.go similarity index 94% rename from pkg/validations/gnss_module.go rename to tgm-collector/pkg/validations/gnss_module.go index 7d0a6496..3c5c4c32 100644 --- a/pkg/validations/gnss_module.go +++ b/tgm-collector/pkg/validations/gnss_module.go @@ -5,8 +5,8 @@ package validations import ( "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gnss_protocol_version.go b/tgm-collector/pkg/validations/gnss_protocol_version.go similarity index 94% rename from pkg/validations/gnss_protocol_version.go rename to tgm-collector/pkg/validations/gnss_protocol_version.go index c79b0adc..617b2b29 100644 --- a/pkg/validations/gnss_protocol_version.go +++ b/tgm-collector/pkg/validations/gnss_protocol_version.go @@ -3,7 +3,7 @@ package validations import ( - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gnss_receiving_data.go b/tgm-collector/pkg/validations/gnss_receiving_data.go similarity index 93% rename from pkg/validations/gnss_receiving_data.go rename to tgm-collector/pkg/validations/gnss_receiving_data.go index 5b331ecc..de43b658 100644 --- a/pkg/validations/gnss_receiving_data.go +++ b/tgm-collector/pkg/validations/gnss_receiving_data.go @@ -5,8 +5,8 @@ package validations import ( "errors" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/gpsd_version.go b/tgm-collector/pkg/validations/gpsd_version.go similarity index 94% rename from pkg/validations/gpsd_version.go rename to tgm-collector/pkg/validations/gpsd_version.go index 24b7b8c1..75f07a72 100644 --- a/pkg/validations/gpsd_version.go +++ b/tgm-collector/pkg/validations/gpsd_version.go @@ -5,7 +5,7 @@ package validations import ( "strings" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" ) const ( diff --git a/pkg/validations/grand_master.go b/tgm-collector/pkg/validations/grand_master.go similarity index 97% rename from pkg/validations/grand_master.go rename to tgm-collector/pkg/validations/grand_master.go index 96f9e079..f695e316 100644 --- a/pkg/validations/grand_master.go +++ b/tgm-collector/pkg/validations/grand_master.go @@ -9,8 +9,8 @@ import ( "fmt" "strings" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" ) const ( diff --git a/pkg/validations/operator_version.go b/tgm-collector/pkg/validations/operator_version.go similarity index 98% rename from pkg/validations/operator_version.go rename to tgm-collector/pkg/validations/operator_version.go index 094808c0..3c869200 100644 --- a/pkg/validations/operator_version.go +++ b/tgm-collector/pkg/validations/operator_version.go @@ -13,7 +13,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" ) const ( diff --git a/pkg/verify/result.go b/tgm-collector/pkg/verify/result.go similarity index 84% rename from pkg/verify/result.go rename to tgm-collector/pkg/verify/result.go index 65a54592..46fba9ce 100644 --- a/pkg/verify/result.go +++ b/tgm-collector/pkg/verify/result.go @@ -6,9 +6,9 @@ import ( "errors" "fmt" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/validations" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + validationsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/validations" ) type resType int @@ -20,7 +20,7 @@ const ( ) type ValidationResult struct { - validation validations.Validation + validation validationsBase.Validation err error resType resType } @@ -66,7 +66,7 @@ func (res *ValidationResult) GetPrefixedError() error { return fmt.Errorf("%s: %w", res.validation.GetDescription(), res.err) } -func NewValidationResult(validation validations.Validation) *ValidationResult { +func NewValidationResult(validation validationsBase.Validation) *ValidationResult { result := resTypeUnknown err := validation.Verify() if err != nil { diff --git a/pkg/verify/verify.go b/tgm-collector/pkg/verify/verify.go similarity index 88% rename from pkg/verify/verify.go rename to tgm-collector/pkg/verify/verify.go index 4d61d7dd..bdb1b05b 100644 --- a/pkg/verify/verify.go +++ b/tgm-collector/pkg/verify/verify.go @@ -10,12 +10,13 @@ import ( log "github.com/sirupsen/logrus" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/callbacks" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/clients" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/contexts" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors/devices" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils" - "github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/validations" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/callbacks" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/clients" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/utils" + validationsBase "github.com/redhat-partner-solutions/vse-sync-collection-tools/collector-framework/pkg/validations" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/contexts" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/collectors/devices" + "github.com/redhat-partner-solutions/vse-sync-collection-tools/tgm-collector/pkg/validations" ) const ( @@ -27,7 +28,7 @@ const ( func getDevInfoValidations( clientset *clients.Clientset, interfaceName string, -) []validations.Validation { +) []validationsBase.Validation { ctx, err := contexts.GetPTPDaemonContext(clientset) utils.IfErrorExitOrPanic(err) devInfo, err := devices.GetPTPDeviceInfo(interfaceName, ctx) @@ -35,17 +36,17 @@ func getDevInfoValidations( devDetails := validations.NewDeviceDetails(&devInfo) devFirmware := validations.NewDeviceFirmware(&devInfo) devDriver := validations.NewDeviceDriver(&devInfo) - return []validations.Validation{devDetails, devFirmware, devDriver} + return []validationsBase.Validation{devDetails, devFirmware, devDriver} } func getGPSVersionValidations( clientset *clients.Clientset, -) []validations.Validation { +) []validationsBase.Validation { ctx, err := contexts.GetPTPDaemonContext(clientset) utils.IfErrorExitOrPanic(err) gnssVersions, err := devices.GetGPSVersions(ctx) utils.IfErrorExitOrPanic(err) - return []validations.Validation{ + return []validationsBase.Validation{ validations.NewGNSS(&gnssVersions), validations.NewGPSDVersion(&gnssVersions), validations.NewGNSDevices(&gnssVersions), @@ -56,7 +57,7 @@ func getGPSVersionValidations( func getGPSStatusValidation( clientset *clients.Clientset, -) []validations.Validation { +) []validationsBase.Validation { ctx, err := contexts.GetPTPDaemonContext(clientset) utils.IfErrorExitOrPanic(err) @@ -74,14 +75,14 @@ func getGPSStatusValidation( time.Sleep(time.Second) } utils.IfErrorExitOrPanic(err) - return []validations.Validation{ + return []validationsBase.Validation{ antCheck, validations.NewGNSSNavStatus(&gpsDetails), } } -func getValidations(interfaceName, kubeConfig string) []validations.Validation { - checks := make([]validations.Validation, 0) +func getValidations(interfaceName, kubeConfig string) []validationsBase.Validation { + checks := make([]validationsBase.Validation, 0) clientset, err := clients.GetClientset(kubeConfig) utils.IfErrorExitOrPanic(err) checks = append(checks, getDevInfoValidations(clientset, interfaceName)...)