From f42936b4677916fad7c745c426e57434543b8eca Mon Sep 17 00:00:00 2001 From: Artur Troian Date: Wed, 14 Aug 2024 16:30:15 -0500 Subject: [PATCH] fix(operator/hostname): enable watcher on provider hostname (#245) - triggers operator watcher to pick changes up when manifest has an update - bump golangci-lint to v1.59.1 - bump go - switch to org registered runners Signed-off-by: Artur Troian --- .github/workflows/integration-tests.yaml | 7 +- .github/workflows/release.yaml | 9 +- .github/workflows/tests.yaml | 23 +- .golangci.yaml | 4 +- .goreleaser.yaml | 2 + bidengine/order_test.go | 2 +- bidengine/pricing_test.go | 2 +- cluster/inventory_test.go | 4 +- cluster/kube/builder/builder.go | 6 + cluster/kube/builder/workload.go | 4 +- cluster/kube/client_exec_test.go | 2 +- cluster/kube/client_hostname_connections.go | 68 ++- .../operators/clients/hostname/client_test.go | 2 +- .../operators/clients/inventory/client.go | 4 +- .../clients/inventory/client_test.go | 4 +- .../kube/operators/clients/ip/client_test.go | 6 +- .../v1beta3/clients/inventory/inventory.go | 5 +- .../v1beta3/clients/inventory/metrics.go | 12 +- .../util/service_discovery_agent_static.go | 2 +- cmd/provider-services/cmd/clusterns.go | 2 +- cmd/provider-services/cmd/leaseEvents.go | 2 +- cmd/provider-services/cmd/leaseLogs.go | 2 +- cmd/provider-services/cmd/leaseStatus.go | 2 +- cmd/provider-services/cmd/run.go | 6 +- cmd/provider-services/cmd/sdl-to-manifest.go | 4 +- cmd/provider-services/cmd/serviceStatus.go | 2 +- gateway/rest/client.go | 6 +- gateway/rest/integration_test.go | 22 +- gateway/rest/middleware.go | 2 +- gateway/rest/router.go | 4 +- go.mod | 6 +- make/init.mk | 2 +- make/lint.mk | 2 +- make/releasing.mk | 8 +- operator/cmd.go | 2 +- operator/common/operator_server.go | 6 +- operator/hostname/cmd.go | 2 +- operator/hostname/operator.go | 43 +- operator/inventory/cmd.go | 6 +- operator/inventory/config.go | 8 +- operator/inventory/node-discovery.go | 6 +- operator/inventory/types.go | 2 +- operator/ip/cmd.go | 2 +- operator/ip/operator.go | 2 +- operator/psutil.go | 9 +- operator/waiter/waiter.go | 2 +- operator/waiter/waiter_test.go | 2 +- script/semver.sh | 331 +++++--------- script/semver_funcs.sh | 417 ++++++++++++++++++ script/tools.sh | 127 +++--- 50 files changed, 787 insertions(+), 420 deletions(-) create mode 100755 script/semver_funcs.sh diff --git a/.github/workflows/integration-tests.yaml b/.github/workflows/integration-tests.yaml index 67a622d8..4848ac60 100644 --- a/.github/workflows/integration-tests.yaml +++ b/.github/workflows/integration-tests.yaml @@ -1,6 +1,7 @@ --- name: Integration tests +# yamllint disable-line rule:truthy on: workflow_call: @@ -15,8 +16,12 @@ jobs: crd-e2e: env: KIND_NAME: kube - runs-on: ubuntu-latest + runs-on: core-e2e steps: + - name: Cleanup build folder + run: | + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true - name: Setup GOPATH run: echo "GOPATH=$GITHUB_WORKSPACE/go" >> $GITHUB_ENV - name: Ensure GOPATH dirs diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f4fa18f2..234b5e54 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,15 +5,20 @@ defaults: run: shell: bash +# yamllint disable-line rule:truthy on: workflow_dispatch: jobs: publish: - runs-on: ubuntu-latest + runs-on: core-e2e env: DOCKER_CLI_EXPERIMENTAL: "enabled" steps: + - name: Cleanup build folder + run: | + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -26,6 +31,8 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8fae65dd..8cd99410 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -5,6 +5,7 @@ defaults: run: shell: bash +# yamllint disable-line rule:truthy on: pull_request: push: @@ -29,6 +30,8 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx @@ -52,6 +55,8 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - run: make test-full lint: @@ -69,14 +74,20 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - name: Run linter run: make lint release-dry-run: - runs-on: ubuntu-latest + runs-on: core-e2e env: DOCKER_CLI_EXPERIMENTAL: "enabled" steps: + - name: Cleanup build folder + run: | + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -89,6 +100,8 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx @@ -116,8 +129,12 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: files: .cache/tests/coverage.txt @@ -136,6 +153,8 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - name: Run codegen run: make codegen - name: Ensure no files changed/added/removed @@ -168,6 +187,8 @@ jobs: go-version: "${{ env.GOVERSION }}" - name: Setup direnv uses: HatsuneMiku3939/direnv-action@v1 + with: + masks: '' - run: make shellcheck integration-tests: diff --git a/.golangci.yaml b/.golangci.yaml index bfc9bc12..c81a0e0b 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -3,9 +3,7 @@ issues: exclude: - comment on exported (method|function|type|const|var) exclude-use-default: true - # Skip generated k8s code -run: skip-dirs: - pkg/client - ".*/mocks" @@ -18,7 +16,7 @@ linters: enable: - unused - misspell - - goerr113 + - err113 - gofmt - gocritic - goconst diff --git a/.goreleaser.yaml b/.goreleaser.yaml index e068a42d..e712dfd4 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,3 +1,5 @@ +--- +version: 2 project_name: provider env: - GO111MODULE=on diff --git a/bidengine/order_test.go b/bidengine/order_test.go index c33c26d7..88fed5a8 100644 --- a/bidengine/order_test.go +++ b/bidengine/order_test.go @@ -122,7 +122,7 @@ func makeMocks(s *orderTestScaffold) { s.cluster = &clustermocks.Cluster{} s.reserveCallNotify = make(chan int, 1) - s.cluster.On("Reserve", s.orderID, &(groupResult.Group)).Run(func(args mock.Arguments) { + s.cluster.On("Reserve", s.orderID, &(groupResult.Group)).Run(func(_ mock.Arguments) { s.reserveCallNotify <- 0 time.Sleep(time.Second) // add a delay before returning response, to test race conditions }).Return(mockReservation, nil) diff --git a/bidengine/pricing_test.go b/bidengine/pricing_test.go index f3d4a33d..9226a209 100644 --- a/bidengine/pricing_test.go +++ b/bidengine/pricing_test.go @@ -687,7 +687,7 @@ func Test_ScriptPricingFromScript(t *testing.T) { expectedPrice := fmt.Sprintf("%.*f", DefaultPricePrecision, 67843137.254901960) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) _, err := io.WriteString(w, mockAPIResponse) require.NoError(t, err) diff --git a/cluster/inventory_test.go b/cluster/inventory_test.go index 8a3da5ff..899169cf 100644 --- a/cluster/inventory_test.go +++ b/cluster/inventory_test.go @@ -523,11 +523,11 @@ func TestInventory_ReserveIPAvailableWithIPOperator(t *testing.T) { ipAddrStatusCalled := make(chan struct{}, 2) // First call indicates no data - mockIP.On("GetIPAddressStatus", mock.Anything, scaffold.leaseIDs[0].OrderID()).Run(func(args mock.Arguments) { + mockIP.On("GetIPAddressStatus", mock.Anything, scaffold.leaseIDs[0].OrderID()).Run(func(_ mock.Arguments) { ipAddrStatusCalled <- struct{}{} }).Return([]cip.LeaseIPStatus{}, nil).Once() // Second call indicates the IP is there and can be confirmed - mockIP.On("GetIPAddressStatus", mock.Anything, scaffold.leaseIDs[0].OrderID()).Run(func(args mock.Arguments) { + mockIP.On("GetIPAddressStatus", mock.Anything, scaffold.leaseIDs[0].OrderID()).Run(func(_ mock.Arguments) { ipAddrStatusCalled <- struct{}{} }).Return([]cip.LeaseIPStatus{ { diff --git a/cluster/kube/builder/builder.go b/cluster/kube/builder/builder.go index 73aa163e..92a205d4 100644 --- a/cluster/kube/builder/builder.go +++ b/cluster/kube/builder/builder.go @@ -35,6 +35,12 @@ const ( AkashLeaseOSeqLabelName = "akash.network/lease.id.oseq" AkashLeaseProviderLabelName = "akash.network/lease.id.provider" AkashLeaseManifestVersion = "akash.network/manifest.version" + AkashLeaseUpdatedAt = "akash.network/lease.updated_at" +) + +const ( + ValTrue = "true" + ValFalse = "false" ) const ( diff --git a/cluster/kube/builder/workload.go b/cluster/kube/builder/workload.go index aa30612b..a8a9ec8c 100644 --- a/cluster/kube/builder/workload.go +++ b/cluster/kube/builder/workload.go @@ -130,8 +130,8 @@ func (b *Workload) container() corev1.Container { // fixme: ram is never expected to be nil if mem := service.Resources.Memory; mem != nil { - requestedRam := sdlutil.ComputeCommittedResources(b.settings.MemoryCommitLevel, mem.Quantity) - kcontainer.Resources.Requests[corev1.ResourceMemory] = resource.NewQuantity(int64(requestedRam.Value()), resource.DecimalSI).DeepCopy() + requestedRAM := sdlutil.ComputeCommittedResources(b.settings.MemoryCommitLevel, mem.Quantity) + kcontainer.Resources.Requests[corev1.ResourceMemory] = resource.NewQuantity(int64(requestedRAM.Value()), resource.DecimalSI).DeepCopy() kcontainer.Resources.Limits[corev1.ResourceMemory] = resource.NewQuantity(int64(mem.Quantity.Value()+requestedMem), resource.DecimalSI).DeepCopy() } diff --git a/cluster/kube/client_exec_test.go b/cluster/kube/client_exec_test.go index 0435d758..c76957de 100644 --- a/cluster/kube/client_exec_test.go +++ b/cluster/kube/client_exec_test.go @@ -162,7 +162,7 @@ func withExecTestScaffold(t *testing.T, changePod func(pod *corev1.Pod) error, t UserAgent: "client_exec_test.go", Username: "theusername", Password: "thepassword", - Proxy: func(req *http.Request) (*url.URL, error) { + Proxy: func(_ *http.Request) (*url.URL, error) { return nil, errNoSPDYInTest }, }, diff --git a/cluster/kube/client_hostname_connections.go b/cluster/kube/client_hostname_connections.go index acbbde36..d157f3b4 100644 --- a/cluster/kube/client_hostname_connections.go +++ b/cluster/kube/client_hostname_connections.go @@ -4,8 +4,9 @@ import ( "context" "fmt" "strings" + "time" - kubeErrors "k8s.io/apimachinery/pkg/api/errors" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" @@ -39,29 +40,39 @@ func (c *client) DeclareHostname(ctx context.Context, lID mtypes.LeaseID, host s labels := map[string]string{ builder.AkashManagedLabelName: "true", } - builder.AppendLeaseLabels(lID, labels) - foundEntry, err := c.ac.AkashV2beta2().ProviderHosts(c.ns).Get(ctx, host, metav1.GetOptions{}) - exists := true - var resourceVersion string + builder.AppendLeaseLabels(lID, labels) + update := true + obj, err := c.ac.AkashV2beta2().ProviderHosts(c.ns).Get(ctx, host, metav1.GetOptions{}) if err != nil { - if kubeErrors.IsNotFound(err) { - exists = false + if kerrors.IsNotFound(err) { + update = false } else { return err } - } else { - resourceVersion = foundEntry.ObjectMeta.ResourceVersion } - obj := crd.ProviderHost{ - ObjectMeta: metav1.ObjectMeta{ - Name: host, // Name is always the hostname, to prevent duplicates - Labels: labels, - ResourceVersion: resourceVersion, - }, - Spec: crd.ProviderHostSpec{ + if !update { + obj = &crd.ProviderHost{ + ObjectMeta: metav1.ObjectMeta{ + Name: host, // Name is always the hostname, to prevent duplicates + Labels: labels, + }, + Spec: crd.ProviderHostSpec{ + Hostname: host, + Owner: lID.GetOwner(), + Dseq: lID.GetDSeq(), + Oseq: lID.GetOSeq(), + Gseq: lID.GetGSeq(), + Provider: lID.GetProvider(), + ServiceName: serviceName, + ExternalPort: externalPort, + }, + } + } else { + obj.ObjectMeta.Labels = labels + obj.Spec = crd.ProviderHostSpec{ Hostname: host, Owner: lID.GetOwner(), Dseq: lID.GetDSeq(), @@ -70,18 +81,27 @@ func (c *client) DeclareHostname(ctx context.Context, lID mtypes.LeaseID, host s Provider: lID.GetProvider(), ServiceName: serviceName, ExternalPort: externalPort, - }, + } } - c.log.Info("declaring hostname", "lease", lID, "service-name", serviceName, "external-port", externalPort, "host", host) - // Create or update the entry - if exists { - _, err = c.ac.AkashV2beta2().ProviderHosts(c.ns).Update(ctx, &obj, metav1.UpdateOptions{}) + + if obj.Annotations == nil { + obj.Annotations = make(map[string]string) + } + + obj.Annotations[builder.AkashLeaseUpdatedAt] = time.Now().UTC().Format(time.RFC3339) + + if update { + _, err = c.ac.AkashV2beta2().ProviderHosts(c.ns).Update(ctx, obj, metav1.UpdateOptions{}) } else { - obj.ResourceVersion = "" - _, err = c.ac.AkashV2beta2().ProviderHosts(c.ns).Create(ctx, &obj, metav1.CreateOptions{}) + _, err = c.ac.AkashV2beta2().ProviderHosts(c.ns).Create(ctx, obj, metav1.CreateOptions{}) } - return err + + if err != nil { + return err + } + + return nil } func (c *client) PurgeDeclaredHostname(ctx context.Context, lID mtypes.LeaseID, hostname string) error { diff --git a/cluster/kube/operators/clients/hostname/client_test.go b/cluster/kube/operators/clients/hostname/client_test.go index d1166922..87141c8f 100644 --- a/cluster/kube/operators/clients/hostname/client_test.go +++ b/cluster/kube/operators/clients/hostname/client_test.go @@ -4,6 +4,6 @@ import ( "testing" ) -func TestHostnameOperatorClient(t *testing.T) { +func TestHostnameOperatorClient(_ *testing.T) { // TODO: tests here } diff --git a/cluster/kube/operators/clients/inventory/client.go b/cluster/kube/operators/clients/inventory/client.go index 33d25a88..fee996c3 100644 --- a/cluster/kube/operators/clients/inventory/client.go +++ b/cluster/kube/operators/clients/inventory/client.go @@ -261,7 +261,7 @@ func newInventoryConnector(ctx context.Context, svc *corev1.Service, invch chan< } if len(pods.Items) == 0 { - return nil, fmt.Errorf("no inventory pods available") // nolint: goerr113 + return nil, fmt.Errorf("no inventory pods available") // nolint: err113 } var pod *corev1.Pod @@ -274,7 +274,7 @@ func newInventoryConnector(ctx context.Context, svc *corev1.Service, invch chan< } if pod == nil { - return nil, fmt.Errorf("no inventory pods available") // nolint: goerr113 + return nil, fmt.Errorf("no inventory pods available") // nolint: err113 } loop: diff --git a/cluster/kube/operators/clients/inventory/client_test.go b/cluster/kube/operators/clients/inventory/client_test.go index 3dee32f2..e69439c5 100644 --- a/cluster/kube/operators/clients/inventory/client_test.go +++ b/cluster/kube/operators/clients/inventory/client_test.go @@ -230,8 +230,8 @@ func makeInventoryScaffold(t *testing.T) *inventoryScaffold { } // QueryCluster does not need to be implemented as provider only uses stream -func (gm *testInventoryServer) QueryCluster(ctx context.Context, _ *emptypb.Empty) (*inventoryV1.Cluster, error) { - return nil, errors.New("unimplemented") // nolint: goerr113 +func (gm *testInventoryServer) QueryCluster(_ context.Context, _ *emptypb.Empty) (*inventoryV1.Cluster, error) { + return nil, errors.New("unimplemented") // nolint: err113 } func (gm *testInventoryServer) StreamCluster(_ *emptypb.Empty, stream inventoryV1.ClusterRPC_StreamClusterServer) error { diff --git a/cluster/kube/operators/clients/ip/client_test.go b/cluster/kube/operators/clients/ip/client_test.go index 6e7cdb25..d6df4b5b 100644 --- a/cluster/kube/operators/clients/ip/client_test.go +++ b/cluster/kube/operators/clients/ip/client_test.go @@ -58,12 +58,12 @@ func fakeIPOperatorHandler() *fakeOperator { fake.ipUsageResponse.Store([]byte{}) fake.mux.HandleFunc("/health", - func(rw http.ResponseWriter, req *http.Request) { + func(rw http.ResponseWriter, _ *http.Request) { status := atomic.LoadUint32(&fake.healthStatus) rw.WriteHeader(int(status)) }) - fake.mux.HandleFunc("/ip-lease-status/", func(rw http.ResponseWriter, req *http.Request) { + fake.mux.HandleFunc("/ip-lease-status/", func(rw http.ResponseWriter, _ *http.Request) { status := atomic.LoadUint32(&fake.ipLeaseStatusStatus) rw.WriteHeader(int(status)) @@ -71,7 +71,7 @@ func fakeIPOperatorHandler() *fakeOperator { _, _ = io.Copy(rw, bytes.NewReader(body)) }) - fake.mux.HandleFunc("/usage", func(rw http.ResponseWriter, req *http.Request) { + fake.mux.HandleFunc("/usage", func(rw http.ResponseWriter, _ *http.Request) { status := atomic.LoadUint32(&fake.ipUsageStatus) rw.WriteHeader(int(status)) diff --git a/cluster/types/v1beta3/clients/inventory/inventory.go b/cluster/types/v1beta3/clients/inventory/inventory.go index 9211097f..9b9c1291 100644 --- a/cluster/types/v1beta3/clients/inventory/inventory.go +++ b/cluster/types/v1beta3/clients/inventory/inventory.go @@ -5,6 +5,7 @@ import ( "reflect" "strings" + "github.com/akash-network/node/sdl" "golang.org/x/net/context" "golang.org/x/sync/errgroup" "k8s.io/apimachinery/pkg/api/resource" @@ -190,7 +191,7 @@ func (cl *nullInventory) run() error { attrs, _ := ParseStorageAttributes(storage.Attributes) if !attrs.Persistent { - if attrs.Class == "ram" { + if attrs.Class == sdl.StorageClassRAM { ndRes.Memory.Quantity.SubNLZ(storage.Quantity) } else { // ephemeral storage @@ -305,7 +306,7 @@ func (inv *inventory) tryAdjust(node int, res *types.Resources) (*crd.SchedulerP } if !attrs.Persistent { - if attrs.Class == "ram" { + if attrs.Class == sdl.StorageClassRAM { if !nd.Resources.Memory.Quantity.SubNLZ(storage.Quantity) { return nil, false, true } diff --git a/cluster/types/v1beta3/clients/inventory/metrics.go b/cluster/types/v1beta3/clients/inventory/metrics.go index 7eeed7c3..1ef5eabe 100644 --- a/cluster/types/v1beta3/clients/inventory/metrics.go +++ b/cluster/types/v1beta3/clients/inventory/metrics.go @@ -42,19 +42,19 @@ func ParseGPUAttributes(attrs types.Attributes) (GPUAttributes, error) { for _, attr := range attrs { tokens := strings.Split(attr.Key, "/") if len(tokens) < 4 || len(tokens)%2 != 0 { - return GPUAttributes{}, fmt.Errorf("invalid GPU attribute") // nolint: goerr113 + return GPUAttributes{}, fmt.Errorf("invalid GPU attribute") // nolint: err113 } switch tokens[0] { case "vendor": default: - return GPUAttributes{}, fmt.Errorf("unexpected GPU attribute type (%s)", tokens[0]) // nolint: goerr113 + return GPUAttributes{}, fmt.Errorf("unexpected GPU attribute type (%s)", tokens[0]) // nolint: err113 } switch tokens[2] { case "model": default: - return GPUAttributes{}, fmt.Errorf("unexpected GPU attribute type (%s)", tokens[2]) // nolint: goerr113 + return GPUAttributes{}, fmt.Errorf("unexpected GPU attribute type (%s)", tokens[2]) // nolint: err113 } vendor := tokens[1] @@ -84,7 +84,7 @@ func ParseGPUAttributes(attrs types.Attributes) (GPUAttributes, error) { case "pcie": case "sxm": default: - return GPUAttributes{}, fmt.Errorf("unsupported GPU interface (%s)", val) // nolint: goerr113 + return GPUAttributes{}, fmt.Errorf("unsupported GPU interface (%s)", val) // nolint: err113 } mattrs.Interface = val @@ -99,7 +99,7 @@ func ParseGPUAttributes(attrs types.Attributes) (GPUAttributes, error) { case "amd": amd[model] = mattrs default: - return GPUAttributes{}, fmt.Errorf("unsupported GPU vendor (%s)", vendor) // nolint: goerr113 + return GPUAttributes{}, fmt.Errorf("unsupported GPU vendor (%s)", vendor) // nolint: err113 } } @@ -123,7 +123,7 @@ func ParseStorageAttributes(attrs types.Attributes) (StorageAttributes, error) { class, _ := attr.AsString() if persistent && (class == "" || class == "ram") { - return StorageAttributes{}, fmt.Errorf("persistent volume must specify storage class") // nolint: goerr113 + return StorageAttributes{}, fmt.Errorf("persistent volume must specify storage class") // nolint: err113 } res := StorageAttributes{ diff --git a/cluster/util/service_discovery_agent_static.go b/cluster/util/service_discovery_agent_static.go index 6f529a80..114a024f 100644 --- a/cluster/util/service_discovery_agent_static.go +++ b/cluster/util/service_discovery_agent_static.go @@ -11,7 +11,7 @@ type staticServiceDiscoveryAgent net.SRV func (staticServiceDiscoveryAgent) Stop() {} func (staticServiceDiscoveryAgent) DiscoverNow() {} -func (ssda staticServiceDiscoveryAgent) GetClient(ctx context.Context, isHTTPS, secure bool) (ServiceClient, error) { +func (ssda staticServiceDiscoveryAgent) GetClient(_ context.Context, isHTTPS, secure bool) (ServiceClient, error) { proto := "http" if isHTTPS { proto = "https" diff --git a/cmd/provider-services/cmd/clusterns.go b/cmd/provider-services/cmd/clusterns.go index 6411b832..0a5c00c0 100644 --- a/cmd/provider-services/cmd/clusterns.go +++ b/cmd/provider-services/cmd/clusterns.go @@ -16,7 +16,7 @@ func clusterNSCmd() *cobra.Command { Short: "print cluster namespace for given lease ID", Args: cobra.ExactArgs(0), SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { lid, err := mcli.LeaseIDFromFlags(cmd.Flags()) if err != nil { return err diff --git a/cmd/provider-services/cmd/leaseEvents.go b/cmd/provider-services/cmd/leaseEvents.go index ddbba1eb..ce2cbb47 100644 --- a/cmd/provider-services/cmd/leaseEvents.go +++ b/cmd/provider-services/cmd/leaseEvents.go @@ -24,7 +24,7 @@ func leaseEventsCmd() *cobra.Command { Short: "get lease events", SilenceUsage: true, Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { return doLeaseEvents(cmd) }, } diff --git a/cmd/provider-services/cmd/leaseLogs.go b/cmd/provider-services/cmd/leaseLogs.go index f6fe1f92..4044498f 100644 --- a/cmd/provider-services/cmd/leaseLogs.go +++ b/cmd/provider-services/cmd/leaseLogs.go @@ -25,7 +25,7 @@ func leaseLogsCmd() *cobra.Command { Short: "get lease logs", SilenceUsage: true, Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { return doLeaseLogs(cmd) }, } diff --git a/cmd/provider-services/cmd/leaseStatus.go b/cmd/provider-services/cmd/leaseStatus.go index 42e5e931..ce4e6053 100644 --- a/cmd/provider-services/cmd/leaseStatus.go +++ b/cmd/provider-services/cmd/leaseStatus.go @@ -21,7 +21,7 @@ func leaseStatusCmd() *cobra.Command { Short: "get lease status", SilenceUsage: true, Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { return doLeaseStatus(cmd) }, } diff --git a/cmd/provider-services/cmd/run.go b/cmd/provider-services/cmd/run.go index 5eeec75e..91120b9e 100644 --- a/cmd/provider-services/cmd/run.go +++ b/cmd/provider-services/cmd/run.go @@ -119,16 +119,16 @@ func RunCmd() *cobra.Command { Use: "run", Short: "run akash provider", SilenceUsage: true, - PreRunE: func(cmd *cobra.Command, args []string) error { + PreRunE: func(cmd *cobra.Command, _ []string) error { leaseFundsMonInterval := viper.GetDuration(FlagLeaseFundsMonitorInterval) withdrawPeriod := viper.GetDuration(FlagWithdrawalPeriod) if leaseFundsMonInterval < time.Minute || leaseFundsMonInterval > 24*time.Hour { - return errors.Errorf(`flag "%s" contains invalid value. expected >=1m<=24h`, FlagLeaseFundsMonitorInterval) // nolint: goerr113 + return errors.Errorf(`flag "%s" contains invalid value. expected >=1m<=24h`, FlagLeaseFundsMonitorInterval) // nolint: err113 } if withdrawPeriod > 0 && withdrawPeriod < leaseFundsMonInterval { - return errors.Errorf(`flag "%s" value must be > "%s"`, FlagWithdrawalPeriod, FlagLeaseFundsMonitorInterval) // nolint: goerr113 + return errors.Errorf(`flag "%s" value must be > "%s"`, FlagWithdrawalPeriod, FlagLeaseFundsMonitorInterval) // nolint: err113 } group, ctx := errgroup.WithContext(cmd.Context()) diff --git a/cmd/provider-services/cmd/sdl-to-manifest.go b/cmd/provider-services/cmd/sdl-to-manifest.go index 55b05585..d482a63a 100644 --- a/cmd/provider-services/cmd/sdl-to-manifest.go +++ b/cmd/provider-services/cmd/sdl-to-manifest.go @@ -17,13 +17,13 @@ func SDL2ManifestCmd() *cobra.Command { Args: cobra.ExactArgs(1), Short: "Dump manifest derived from the SDL", SilenceUsage: true, - PreRunE: func(cmd *cobra.Command, args []string) error { + PreRunE: func(cmd *cobra.Command, _ []string) error { format := cmd.Flag(flagOutput).Value.String() switch format { case outputJSON: case outputYAML: default: - return fmt.Errorf("invalid output format \"%s\", expected json|yaml", format) // nolint: goerr113 + return fmt.Errorf("invalid output format \"%s\", expected json|yaml", format) // nolint: err113 } return nil diff --git a/cmd/provider-services/cmd/serviceStatus.go b/cmd/provider-services/cmd/serviceStatus.go index 86a3162c..c47918c8 100644 --- a/cmd/provider-services/cmd/serviceStatus.go +++ b/cmd/provider-services/cmd/serviceStatus.go @@ -21,7 +21,7 @@ func serviceStatusCmd() *cobra.Command { Short: "get service status", SilenceUsage: true, Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { return doServiceStatus(cmd) }, } diff --git a/gateway/rest/client.go b/gateway/rest/client.go index 718f2f46..f3439167 100644 --- a/gateway/rest/client.go +++ b/gateway/rest/client.go @@ -148,7 +148,7 @@ func (c *client) newReqClient(ctx context.Context) *reqClient { TLSClientConfig: tlsConfig, }, // Never follow redirects - CheckRedirect: func(req *http.Request, via []*http.Request) error { + CheckRedirect: func(_ *http.Request, _ []*http.Request) error { return http.ErrUseLastResponse }, Jar: nil, @@ -280,7 +280,7 @@ func (c *client) GetJWT(ctx context.Context) (*jwt.Token, error) { return nil, err } - token, err := jwt.ParseWithClaims(responseBuf.String(), &ClientCustomClaims{}, func(token *jwt.Token) (interface{}, error) { + token, err := jwt.ParseWithClaims(responseBuf.String(), &ClientCustomClaims{}, func(_ *jwt.Token) (interface{}, error) { // return the public key to be used for JWT verification return resp.TLS.PeerCertificates[0].PublicKey.(*ecdsa.PublicKey), nil }) @@ -690,7 +690,7 @@ func (c *client) LeaseLogs(ctx context.Context, id mtypes.LeaseID, services string, follow bool, - tailLines int64) (*ServiceLogs, error) { + _ int64) (*ServiceLogs, error) { endpoint, err := url.Parse(c.host.String() + "/" + serviceLogsPath(id)) if err != nil { diff --git a/gateway/rest/integration_test.go b/gateway/rest/integration_test.go index d3fb20e7..60befa46 100644 --- a/gateway/rest/integration_test.go +++ b/gateway/rest/integration_test.go @@ -1,4 +1,4 @@ -// nolint: goerr113 +// nolint: err113 package rest import ( @@ -35,7 +35,7 @@ func Test_router_Status(t *testing.T) { mocks := createMocks() mocks.pclient.On("Status", mock.Anything).Return(expected, nil) - withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(_ string) { client, err := NewClient(context.Background(), mocks.qclient, addr, nil) assert.NoError(t, err) result, err := client.Status(context.Background()) @@ -49,7 +49,7 @@ func Test_router_Status(t *testing.T) { addr := testutil.AccAddress(t) mocks := createMocks() mocks.pclient.On("Status", mock.Anything).Return(nil, errors.New("oops")) - withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(_ string) { client, err := NewClient(context.Background(), mocks.qclient, addr, nil) assert.NoError(t, err) _, err = client.Status(context.Background()) @@ -67,7 +67,7 @@ func Test_router_Validate(t *testing.T) { addr := testutil.AccAddress(t) mocks := createMocks() mocks.pclient.On("Validate", mock.Anything, mock.Anything, mock.Anything).Return(expected, nil) - withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, testutil.AccAddress(t), testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, addr, cert.Cert) assert.NoError(t, err) @@ -82,7 +82,7 @@ func Test_router_Validate(t *testing.T) { addr := testutil.AccAddress(t) mocks := createMocks() mocks.pclient.On("Validate", mock.Anything, mock.Anything, mock.Anything).Return(provider.ValidateGroupSpecResult{}, errors.New("oops")) - withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, addr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, testutil.AccAddress(t), testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, addr, cert.Cert) assert.NoError(t, err) @@ -104,7 +104,7 @@ func Test_router_Manifest(t *testing.T) { mocks := createMocks() mocks.pmclient.On("Submit", mock.Anything, did, akashmanifest.Manifest(nil)).Return(nil) - withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, caddr, testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, paddr, cert.Cert) assert.NoError(t, err) @@ -123,7 +123,7 @@ func Test_router_Manifest(t *testing.T) { mocks := createMocks() mocks.pmclient.On("Submit", mock.Anything, did, akashmanifest.Manifest(nil)).Return(errors.New("ded")) - withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, caddr, testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, paddr, cert.Cert) assert.NoError(t, err) @@ -207,7 +207,7 @@ func Test_router_LeaseStatus(t *testing.T) { mockManifestGroups(mocks, id) - withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, caddr, testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, paddr, cert.Cert) assert.NoError(t, err) @@ -245,7 +245,7 @@ func Test_router_LeaseStatus(t *testing.T) { mocks.pcclient.On("LeaseStatus", mock.Anything, id).Return(nil, errors.New("ded")) mockManifestGroups(mocks, id) - withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, caddr, testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, paddr, cert.Cert) assert.NoError(t, err) @@ -270,7 +270,7 @@ func Test_router_ServiceStatus(t *testing.T) { mocks := createMocks() mocks.pcclient.On("ServiceStatus", mock.Anything, id, service).Return(expected, nil) - withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, caddr, testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, paddr, cert.Cert) assert.NoError(t, err) @@ -292,7 +292,7 @@ func Test_router_ServiceStatus(t *testing.T) { mocks := createMocks() mocks.pcclient.On("ServiceStatus", mock.Anything, id, service).Return(nil, errors.New("ded")) - withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(host string) { + withServer(t, paddr, mocks.pclient, mocks.qclient, nil, func(_ string) { cert := testutil.Certificate(t, caddr, testutil.CertificateOptionMocks(mocks.qclient)) client, err := NewClient(context.Background(), mocks.qclient, paddr, cert.Cert) assert.NoError(t, err) diff --git a/gateway/rest/middleware.go b/gateway/rest/middleware.go index 6848d856..6d132e74 100644 --- a/gateway/rest/middleware.go +++ b/gateway/rest/middleware.go @@ -217,7 +217,7 @@ func resourceServerAuth(log log.Logger, providerAddr sdk.Address, publicKey *ecd return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // verify the provided JWT - token, err := jwt.ParseWithClaims(r.Header.Get("Authorization"), &ClientCustomClaims{}, func(token *jwt.Token) (interface{}, error) { + token, err := jwt.ParseWithClaims(r.Header.Get("Authorization"), &ClientCustomClaims{}, func(_ *jwt.Token) (interface{}, error) { // return the public key to be used for JWT verification return publicKey, nil }) diff --git a/gateway/rest/router.go b/gateway/rest/router.go index 0c01a883..75f1a54b 100644 --- a/gateway/rest/router.go +++ b/gateway/rest/router.go @@ -478,7 +478,7 @@ func leaseShellHandler(log log.Logger, mclient pmanifest.Client, cclient cluster } func createAddressHandler(log log.Logger, providerAddr sdk.Address) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { + return func(w http.ResponseWriter, _ *http.Request) { data := struct { Address string `json:"address"` }{ @@ -494,7 +494,7 @@ type versionInfo struct { } func createVersionHandler(log log.Logger, pclient provider.Client) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, _ *http.Request) { kube, err := pclient.Cluster().KubeVersion() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/go.mod b/go.mod index f1c50851..4261615a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/akash-network/provider -go 1.21 +go 1.22.6 require ( github.com/akash-network/akash-api v0.0.67 @@ -49,9 +49,7 @@ require ( sigs.k8s.io/kind v0.20.0 ) -retract ( - v0.6.0 -) +retract v0.6.0 replace ( // use cosmos fork of keyring diff --git a/make/init.mk b/make/init.mk index 62e70859..99f90f0c 100644 --- a/make/init.mk +++ b/make/init.mk @@ -87,7 +87,7 @@ AKASHD_SRC_IS_LOCAL := $(shell $(ROOT_DIR)/script/is_local_gomod.sh "$( AKASHD_LOCAL_PATH := $(shell $(GO) list -mod=readonly -m -f '{{ .Dir }}' "$(AKASHD_MODULE)") AKASHD_VERSION := $(shell $(GO) list -mod=readonly -m -f '{{ .Version }}' $(AKASHD_MODULE) | cut -c2-) GRPC_GATEWAY_VERSION := $(shell $(GO) list -mod=readonly -m -f '{{ .Version }}' github.com/grpc-ecosystem/grpc-gateway) -GOLANGCI_LINT_VERSION ?= v1.51.2 +GOLANGCI_LINT_VERSION ?= v1.59.1 STATIK_VERSION ?= v0.1.7 GIT_CHGLOG_VERSION ?= v0.15.1 MOCKERY_PACKAGE_NAME := github.com/vektra/mockery/v2 diff --git a/make/lint.mk b/make/lint.mk index 93ff8e99..9376ec78 100644 --- a/make/lint.mk +++ b/make/lint.mk @@ -1,6 +1,6 @@ .PHONY: lint lint: $(GOLANGCI_LINT) - $(GOLANGCI_LINT_RUN) ./... --issues-exit-code=0 --deadline=20m + $(GOLANGCI_LINT_RUN) ./... --issues-exit-code=0 --timeout=20m .PHONY: lint-% lint-%: $(GOLANGCI_LINT) diff --git a/make/releasing.mk b/make/releasing.mk index 9beb073d..b842b194 100644 --- a/make/releasing.mk +++ b/make/releasing.mk @@ -30,6 +30,10 @@ ifeq ($(DETECTED_OS), Darwin) export CGO_CFLAGS=-Wno-deprecated-declarations endif +.PHONY: bump-% +bump-%: + @./script/tools.sh bump "$*" + .PHONY: bins bins: $(BINS) @@ -75,7 +79,7 @@ docker-image: -w /go/src/$(GO_MOD_NAME) \ $(GORELEASER_IMAGE) \ -f .goreleaser-docker.yaml \ - --debug=$(GORELEASER_DEBUG) \ + --verbose=$(GORELEASER_DEBUG) \ --clean \ --skip=publish,validate \ --snapshot @@ -108,6 +112,6 @@ release: gen-changelog -f "$(GORELEASER_CONFIG)" \ release \ $(GORELEASER_SKIP) \ - --debug=$(GORELEASER_DEBUG) \ + --verbose=$(GORELEASER_DEBUG) \ --clean \ --release-notes=/go/src/$(GO_MOD_NAME)/.cache/changelog.md diff --git a/operator/cmd.go b/operator/cmd.go index 08549d58..ff77d082 100644 --- a/operator/cmd.go +++ b/operator/cmd.go @@ -29,7 +29,7 @@ func OperatorsCmd() *cobra.Command { Use: "operator", Short: "kubernetes operators control", SilenceUsage: true, - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { zconf := zap.NewDevelopmentConfig() zconf.DisableCaller = true zconf.DisableStacktrace = true diff --git a/operator/common/operator_server.go b/operator/common/operator_server.go index 7146ac3c..fa86c6c4 100644 --- a/operator/common/operator_server.go +++ b/operator/common/operator_server.go @@ -35,7 +35,7 @@ func NewOperatorHTTP() (OperatorHTTP, error) { results: make(map[string]preparedEntry), } - retval.router.HandleFunc("/health", func(rw http.ResponseWriter, req *http.Request) { + retval.router.HandleFunc("/health", func(rw http.ResponseWriter, _ *http.Request) { rw.WriteHeader(http.StatusOK) _, _ = io.WriteString(rw, "OK") }) @@ -53,7 +53,7 @@ func NewOperatorHTTP() (OperatorHTTP, error) { buf = nil // remove from scope enc = nil // remove from scope - retval.router.HandleFunc("/version", func(rw http.ResponseWriter, req *http.Request) { + retval.router.HandleFunc("/version", func(rw http.ResponseWriter, _ *http.Request) { rw.WriteHeader(http.StatusOK) _, _ = io.Copy(rw, bytes.NewReader(akashVersionJSON)) }).Methods("GET") @@ -80,7 +80,7 @@ func (opHttp *operatorHTTP) AddPreparedEndpoint(path string, prepare PrepareFn) } opHttp.results[path] = entry - opHttp.router.HandleFunc(path, func(rw http.ResponseWriter, req *http.Request) { + opHttp.router.HandleFunc(path, func(rw http.ResponseWriter, _ *http.Request) { servePreparedResult(rw, entry.data) }).Methods(http.MethodGet) diff --git a/operator/hostname/cmd.go b/operator/hostname/cmd.go index 2c9fe4d7..2c3436d1 100644 --- a/operator/hostname/cmd.go +++ b/operator/hostname/cmd.go @@ -19,7 +19,7 @@ func Cmd() *cobra.Command { Use: "hostname", Short: "kubernetes operator interfacing with k8s nginx ingress", SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := cmd.Context() group := fromctx.MustErrGroupFromCtx(ctx) diff --git a/operator/hostname/operator.go b/operator/hostname/operator.go index e210eefb..d299d726 100644 --- a/operator/hostname/operator.go +++ b/operator/hostname/operator.go @@ -415,22 +415,22 @@ func (op *hostnameOperator) applyAddOrUpdateEvent(ctx context.Context, ev chostn directive := buildDirective(ev, selectedExpose) if isSameLease { - shouldConnect := false + // shouldConnect := false if !exists { - shouldConnect = true + // shouldConnect = true op.log.Debug("hostname target is new, applying") // Check to see if port or service name is different } else if entry.presentExternalPort != ev.GetExternalPort() || entry.presentServiceName != ev.GetServiceName() { - shouldConnect = true + // shouldConnect = true op.log.Debug("hostname target has changed, applying") } - if shouldConnect { - op.log.Debug("Updating ingress") - // Update or create the existing ingress - err = op.connectHostnameToDeployment(ctx, directive) - } + // if shouldConnect { + op.log.Debug("Updating ingress") + // Update or create the existing ingress + err = op.connectHostnameToDeployment(ctx, directive) + // } } else { op.log.Debug("Swapping ingress to new deployment") // Delete the ingress in one namespace and recreate it in the correct one @@ -464,7 +464,6 @@ func (op *hostnameOperator) getHostnameDeploymentConnections(ctx context.Context err := ingressPager.EachListItem(ctx, metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=true", builder.AkashManagedLabelName)}, func(obj runtime.Object) error { - ingress := obj.(*netv1.Ingress) ingressLeaseID, err := clientcommon.RecoverLeaseIDFromLabels(ingress.Labels) if err != nil { @@ -497,13 +496,8 @@ func (op *hostnameOperator) getHostnameDeploymentConnections(ctx context.Context } func (op *hostnameOperator) observeHostnameState(ctx context.Context) (<-chan chostname.ResourceEvent, error) { - var lastResourceVersion string phpager := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) { resources, err := op.ac.AkashV2beta2().ProviderHosts(op.ns).List(ctx, opts) - - if err == nil && len(resources.GetResourceVersion()) != 0 { - lastResourceVersion = resources.GetResourceVersion() - } return resources, err }) @@ -518,19 +512,8 @@ func (op *hostnameOperator) observeHostnameState(ctx context.Context) (<-chan ch return nil, err } - op.log.Info("starting hostname watch", "resourceVersion", lastResourceVersion) - watcher, err := op.ac.AkashV2beta2().ProviderHosts(op.ns).Watch(ctx, metav1.ListOptions{ - TypeMeta: metav1.TypeMeta{}, - LabelSelector: "", - FieldSelector: "", - Watch: false, - AllowWatchBookmarks: false, - ResourceVersion: lastResourceVersion, - ResourceVersionMatch: "", - TimeoutSeconds: nil, - Limit: 0, - Continue: "", - }) + op.log.Info("starting hostname watch") // , "resourceVersion", lastResourceVersion) + watcher, err := op.ac.AkashV2beta2().ProviderHosts(op.ns).Watch(ctx, metav1.ListOptions{}) if err != nil { return nil, err } @@ -564,7 +547,11 @@ func (op *hostnameOperator) observeHostnameState(ctx context.Context) (<-chan ch output := make(chan chostname.ResourceEvent) go func() { - defer close(output) + defer func() { + close(output) + watcher.Stop() + }() + for _, v := range evData { output <- v } diff --git a/operator/inventory/cmd.go b/operator/inventory/cmd.go index 1d12b8c5..9be16f4d 100644 --- a/operator/inventory/cmd.go +++ b/operator/inventory/cmd.go @@ -51,7 +51,7 @@ func Cmd() *cobra.Command { Use: "inventory", Short: "kubernetes operator interfacing inventory", SilenceUsage: true, - PreRunE: func(cmd *cobra.Command, args []string) error { + PreRunE: func(cmd *cobra.Command, _ []string) error { kubecfg := fromctx.MustKubeConfigFromCtx(cmd.Context()) rc, err := rookclientset.NewForConfig(kubecfg) @@ -63,7 +63,7 @@ func Cmd() *cobra.Command { return nil }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := cmd.Context() log := fromctx.LogrFromCtx(cmd.Context()) @@ -359,7 +359,7 @@ func registryLoader(ctx context.Context) error { cl := &http.Client{ Transport: &http.Transport{ - DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + DialTLSContext: func(_ context.Context, network, addr string) (net.Conn, error) { return tls.Dial(network, addr, tlsConfig) }, }, diff --git a/operator/inventory/config.go b/operator/inventory/config.go index 269449d4..31a72ec1 100644 --- a/operator/inventory/config.go +++ b/operator/inventory/config.go @@ -195,7 +195,7 @@ loop: case "exclude": val = &res.Exclude default: - return fmt.Errorf("config: unexpected field %s", node.Content[i].Value) // nolint: goerr113 + return fmt.Errorf("config: unexpected field %s", node.Content[i].Value) // nolint: err113 } if err := node.Content[i+1].Decode(val); err != nil { @@ -211,7 +211,7 @@ loop: for _, exl := range res.Exclude.NodeStorage { for _, sc := range exl.Classes { if _, exists := availSc[sc]; !exists { - return fmt.Errorf("storage class \"%s\" from exclude references non-existing class", sc) // nolint: goerr113 + return fmt.Errorf("storage class \"%s\" from exclude references non-existing class", sc) // nolint: err113 } } @@ -235,7 +235,7 @@ func (nd *ExcludeRules) UnmarshalYAML(node *yaml.Node) error { res := make(ExcludeRules, 0, len(excludes)) for i, ex := range excludes { if ex == "" { - return fmt.Errorf("empty regexp filters are not allowed") // nolint: goerr113 + return fmt.Errorf("empty regexp filters are not allowed") // nolint: err113 } r, err := regexp.Compile(ex) @@ -262,7 +262,7 @@ func (nd *ExcludeNodeStorage) UnmarshalYAML(node *yaml.Node) error { } if tmp.NodeFilter == "" { - return fmt.Errorf("empty regexp filters are not allowed") // nolint: goerr113 + return fmt.Errorf("empty regexp filters are not allowed") // nolint: err113 } r, err := regexp.Compile(tmp.NodeFilter) diff --git a/operator/inventory/node-discovery.go b/operator/inventory/node-discovery.go index f840d305..f4255183 100644 --- a/operator/inventory/node-discovery.go +++ b/operator/inventory/node-discovery.go @@ -596,11 +596,11 @@ func (dp *nodeDiscovery) monitor() error { } } -func (dp *nodeDiscovery) initNodeInfo(gpusIds RegistryGPUVendors) (v1.Node, error) { +func (dp *nodeDiscovery) initNodeInfo(gpusIDs RegistryGPUVendors) (v1.Node, error) { kc := fromctx.MustKubeClientFromCtx(dp.ctx) cpuInfo := dp.parseCPUInfo(dp.ctx) - gpuInfo := dp.parseGPUInfo(dp.ctx, gpusIds) + gpuInfo := dp.parseGPUInfo(dp.ctx, gpusIDs) knode, err := kc.CoreV1().Nodes().Get(dp.ctx, dp.name, metav1.GetOptions{}) if err != nil { @@ -772,7 +772,7 @@ func generateLabels(cfg Config, knode *corev1.Node, node v1.Node, sc storageClas return res, node } - res[builder.AkashManagedLabelName] = "true" + res[builder.AkashManagedLabelName] = builder.ValTrue allowedSc := adjConfig.StorageClassesForNode(knode.Name) for _, class := range allowedSc { diff --git a/operator/inventory/types.go b/operator/inventory/types.go index 87c7ea33..5c23f1ab 100644 --- a/operator/inventory/types.go +++ b/operator/inventory/types.go @@ -192,7 +192,7 @@ func InformKubeObjects(ctx context.Context, pub pubsub.Publisher, informer cache Object: obj.(runtime.Object), }, []string{topic}) }, - UpdateFunc: func(oldObj, newObj interface{}) { + UpdateFunc: func(_, newObj interface{}) { pub.Pub(watch.Event{ Type: watch.Modified, Object: newObj.(runtime.Object), diff --git a/operator/ip/cmd.go b/operator/ip/cmd.go index 71a91f2a..432f56d3 100644 --- a/operator/ip/cmd.go +++ b/operator/ip/cmd.go @@ -27,7 +27,7 @@ func Cmd() *cobra.Command { Use: "ip", Short: "kubernetes operator interfacing with Metal LB", SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ns := viper.GetString(providerflags.FlagK8sManifestNS) poolName := viper.GetString(flagMetalLbPoolName) logger := common.OpenLogger().With("operator", "ip") diff --git a/operator/ip/operator.go b/operator/ip/operator.go index 73c36093..4d7b90cd 100644 --- a/operator/ip/operator.go +++ b/operator/ip/operator.go @@ -500,7 +500,7 @@ func newIPOperator(ctx context.Context, logger log.Logger, ns string, cfg common retval.flagIgnoredLeases = retval.server.AddPreparedEndpoint("/ignored-leases", retval.leasesIgnored.Prepare) retval.flagUsage = retval.server.AddPreparedEndpoint("/usage", retval.prepareUsage) - retval.server.GetRouter().HandleFunc("/health", func(rw http.ResponseWriter, req *http.Request) { + retval.server.GetRouter().HandleFunc("/health", func(rw http.ResponseWriter, _ *http.Request) { rw.WriteHeader(http.StatusOK) _, _ = io.WriteString(rw, "OK") }) diff --git a/operator/psutil.go b/operator/psutil.go index faaa13d7..44ab7fbd 100644 --- a/operator/psutil.go +++ b/operator/psutil.go @@ -37,8 +37,7 @@ func cmdPsutil() *cobra.Command { Short: "dump node hardware spec", Args: cobra.ExactArgs(0), SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { - + RunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -55,7 +54,7 @@ func cmdPsutilServe() *cobra.Command { Short: "dump node hardware spec via REST", Args: cobra.ExactArgs(0), SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { router := mux.NewRouter() router.HandleFunc("/", infoHandler).Methods(http.MethodGet) @@ -117,7 +116,7 @@ func cmdPsutilList() *cobra.Command { Short: "dump node hardware spec into stdout", Args: cobra.ExactArgs(1), SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { var res interface{} var err error switch args[0] { @@ -130,7 +129,7 @@ func cmdPsutilList() *cobra.Command { case "pci": res, err = pci.New() default: - return fmt.Errorf("invalid command \"%s\"", args[0]) // nolint: goerr113 + return fmt.Errorf("invalid command \"%s\"", args[0]) // nolint: err113 } if err != nil { diff --git a/operator/waiter/waiter.go b/operator/waiter/waiter.go index 73e9417c..788b0849 100644 --- a/operator/waiter/waiter.go +++ b/operator/waiter/waiter.go @@ -18,7 +18,7 @@ type Waitable interface { type nullWaiter struct{} -func (nw nullWaiter) WaitForAll(ctx context.Context) error { +func (nw nullWaiter) WaitForAll(_ context.Context) error { return nil } diff --git a/operator/waiter/waiter_test.go b/operator/waiter/waiter_test.go index d7cf6384..be2960b6 100644 --- a/operator/waiter/waiter_test.go +++ b/operator/waiter/waiter_test.go @@ -34,7 +34,7 @@ type fakeWaiter struct { failure error } -func (fw fakeWaiter) Check(ctx context.Context) error { +func (fw fakeWaiter) Check(_ context.Context) error { return fw.failure } diff --git a/script/semver.sh b/script/semver.sh index abdecaa3..768cec25 100755 --- a/script/semver.sh +++ b/script/semver.sh @@ -1,256 +1,131 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 set -o errexit -o nounset -o pipefail -SEMVER_REGEX="^[v|V]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" -SEMVER_REGEX_LEGACY="^[v|V]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\.0|[1-9][0-9]*)?(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$" +source "$SCRIPT_DIR/semver_funcs.sh" PROG=semver -PROG_VERSION=2.1.0 +PROG_VERSION="3.4.0" USAGE="\ Usage: - $PROG bump (major|minor|patch|release|prerel |build ) + $PROG bump major + $PROG bump minor + $PROG bump patch + $PROG bump prerel|prerelease [] + $PROG bump build + $PROG bump release + $PROG get major + $PROG get minor + $PROG get patch + $PROG get prerel|prerelease + $PROG get build + $PROG get release $PROG compare - $PROG get (major|minor|patch|release|prerel|build) + $PROG diff + $PROG validate $PROG --help $PROG --version -Arguments: - A version must match the following regex pattern: - \"${SEMVER_REGEX}\". - In english, the version must match X.Y.Z(-PRERELEASE)(+BUILD) - where X, Y and Z are positive integers, PRERELEASE is an optional - string composed of alphanumeric characters and hyphens and - BUILD is also an optional string composed of alphanumeric - characters and hyphens. - See definition. - String that must be composed of alphanumeric characters and hyphens. - String that must be composed of alphanumeric characters and hyphens. -Options: - -v, --version Print the version of this tool. - -h, --help Print this help message. -Commands: - bump Bump by one of major, minor, patch, prerel, build - or a forced potentially conflicting version. The bumped version is - shown to stdout. - compare Compare with , output to stdout the - following values: -1 if is newer, 0 if equal, 1 if - older. - get Extract given part of , where part is one of major, minor, - patch, prerel, build. - validate Check version string is valid" - - -function error { - echo -e "$1" >&2 - exit 1 -} - -function usage-help { - error "$USAGE" -} - -function usage-version { - echo -e "${PROG}: $PROG_VERSION" - exit 0 -} - -function validate-version { - local version=$1 - if [[ "$version" =~ $SEMVER_REGEX ]]; then - # if a second argument is passed, store the result in var named by $2 - if [[ "$#" -eq "2" ]]; then - local major=${BASH_REMATCH[1]} - local minor=${BASH_REMATCH[2]} - local patch=${BASH_REMATCH[3]} - local prere=${BASH_REMATCH[4]} - local build=${BASH_REMATCH[6]} - eval "$2=(\"${major}\" \"${minor}\" \"${patch}\" \"${prere}\" \"${build}\")" - else - echo "$version" - fi - elif [[ "$version" =~ $SEMVER_REGEX_LEGACY ]]; then - # if a second argument is passed, store the result in var named by $2 - if [[ "$#" -eq "2" ]]; then - local major=${BASH_REMATCH[1]} - local minor=${BASH_REMATCH[2]} - local patch=0 - local prere=${BASH_REMATCH[4]} - local build=${BASH_REMATCH[6]} - eval "$2=(\"${major}\" \"${minor}\" \"${patch}\" \"${prere}\" \"${build}\")" - else - echo "$version" - fi - else - error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information." - fi -} - -function compare-version { - validate-version "$1" V - validate-version "$2" V_ - - # MAJOR, MINOR and PATCH should compare numerically - for i in 0 1 2; do - local diff=$((${V[$i]} - ${V_[$i]})) - if [[ ${diff} -lt 0 ]]; then - echo -1; - return 0 - elif [[ ${diff} -gt 0 ]]; then - echo 1; - return 0 - fi - done - # PREREL should compare with the ASCII order. - if [[ -z "${V[3]}" ]] && [[ -n "${V_[3]}" ]]; then - echo -1; - return 0; - elif [[ -n "${V[3]}" ]] && [[ -z "${V_[3]}" ]]; then - echo 1; - return 0; - elif [[ -n "${V[3]}" ]] && [[ -n "${V_[3]}" ]]; then - if [[ "${V[3]}" > "${V_[3]}" ]]; then - echo 1; - return 0; - elif [[ "${V[3]}" < "${V_[3]}" ]]; then - echo -1; - return 0; - fi - fi - - echo 0 -} - -function command-bump { - local new; - local version; - local sub_version; - local command; - - case $# in - 2) - case $1 in - major | minor | patch | release) - command=$1; - version=$2 ;; - *) - usage-help ;; - esac ;; - 3) - case $1 in - prerel | build) - command=$1; - sub_version=$2 version=$3 ;; - *) - usage-help ;; - esac ;; - *) - usage-help ;; - esac - - validate-version "$version" parts - # shellcheck disable=SC2154 - local major="${parts[0]}" - local minor="${parts[1]}" - local patch="${parts[2]}" - local prere="${parts[3]}" - local build="${parts[4]}" +Arguments: + A version must match the following regular expression: + \"${SEMVER_REGEX}\" + In English: + -- The version must match X.Y.Z[-PRERELEASE][+BUILD] + where X, Y and Z are non-negative integers. + -- PRERELEASE is a dot separated sequence of non-negative integers and/or + identifiers composed of alphanumeric characters and hyphens (with + at least one non-digit). Numeric identifiers must not have leading + zeros. A hyphen (\"-\") introduces this optional part. + -- BUILD is a dot separated sequence of identifiers composed of alphanumeric + characters and hyphens. A plus (\"+\") introduces this optional part. - case "$command" in - major) - new="$((major + 1)).0.0" ;; - minor) - new="${major}.$((minor + 1)).0" ;; - patch) - new="${major}.${minor}.$((patch + 1))" ;; - release) - new="${major}.${minor}.${patch}" ;; - prerel) - new=$(validate-version "${major}.${minor}.${patch}-${sub_version}") ;; - build) - new=$(validate-version "${major}.${minor}.${patch}${prere}+${sub_version}") ;; - *) - usage-help ;; - esac + See definition. - echo "$new" - exit 0 -} + A string as defined by PRERELEASE above. Or, it can be a PRERELEASE + prototype string followed by a dot. -function command-compare { - local v; - local v_; + A string as defined by BUILD above. - case $# in - 2) - v=$(validate-version "$1"); - v_=$(validate-version "$2") ;; - *) - usage-help ;; - esac +Options: + -v, --version Print the version of this tool. + -h, --help Print this help message. - compare-version "$v" "$v_" - exit 0 +Commands: + bump Bump by one of major, minor, patch; zeroing or removing + subsequent parts. \"bump prerel\" (or its synonym \"bump prerelease\") + sets the PRERELEASE part and removes any BUILD part. A trailing dot + in the argument introduces an incrementing numeric field + which is added or bumped. If no argument is provided, an + incrementing numeric field is introduced/bumped. \"bump build\" sets + the BUILD part. \"bump release\" removes any PRERELEASE or BUILD parts. + The bumped version is written to stdout. + + get Extract given part of , where part is one of major, minor, + patch, prerel (alternatively: prerelease), build, or release. + + compare Compare with , output to stdout the + following values: -1 if is newer, 0 if equal, 1 if + older. The BUILD part is not used in comparisons. + + diff Compare with , output to stdout the + difference between two versions by the release type (MAJOR, MINOR, + PATCH, PRERELEASE, BUILD). + + validate Validate if follows the SEMVER pattern (see + definition). Print 'valid' to stdout if the version is valid, otherwise + print 'invalid'. + +See also: + https://semver.org -- Semantic Versioning 2.0.0" + +function usage_help { + error "$USAGE" } -# shellcheck disable=SC2034 -function command-get { - local part version - - if [[ "$#" -ne "2" ]] || [[ -z "$1" ]] || [[ -z "$2" ]]; then - usage-help - fi - - part="$1" - version="$2" - - validate-version "$version" parts - local major="${parts[0]}" - local minor="${parts[1]}" - local patch="${parts[2]}" - local prerel="${parts[3]:1}" - local build="${parts[4]:1}" - - case "$part" in - "major-minor") - echo "$major.$minor" - ;; - major | minor | patch | release | prerel | build) - echo "${!part}" ;; - *) - usage-help ;; - esac - - exit 0 +function usage_version { + echo -e "${PROG}: $PROG_VERSION" + exit 0 } case $# in - 0) - echo "Unknown command: $*"; - usage-help ;; + 0) + echo "Unknown command: $*" + usage_help + ;; esac case $1 in - --help | -h) - echo -e "$USAGE"; - exit 0 ;; - --version | -v) - usage-version ;; - bump) - shift; - command-bump "$@" ;; - get) - shift; - command-get "$@" ;; - compare) - shift; - command-compare "$@" ;; - validate) - shift; - validate-version "$@" V ;; - *) - echo "Unknown arguments: $*"; - usage-help ;; + --help | -h) + echo -e "$USAGE" + exit 0 + ;; + --version | -v) usage_version ;; + bump) + shift + command_bump "$@" + ;; + get) + shift + command_get "$@" + ;; + compare) + shift + command_compare "$@" + ;; + diff) + shift + command_diff "$@" + ;; + validate) + shift + command_validate "$@" + ;; + *) + echo "Unknown arguments: $*" + usage_help + ;; esac diff --git a/script/semver_funcs.sh b/script/semver_funcs.sh new file mode 100755 index 00000000..bd4ece5a --- /dev/null +++ b/script/semver_funcs.sh @@ -0,0 +1,417 @@ +#!/usr/bin/env bash + +NAT='0|[1-9][0-9]*' +ALPHANUM='[0-9]*[A-Za-z-][0-9A-Za-z-]*' +IDENT="$NAT|$ALPHANUM" +FIELD='[0-9A-Za-z-]+' + +SEMVER_REGEX_STR="\ +[vV]?\ +($NAT)\\.($NAT)\\.($NAT)\ +(\\-(${IDENT})(\\.(${IDENT}))*)?\ +(\\+${FIELD}(\\.${FIELD})*)?$" + +SEMVER_REGEX_LEGACY="\ +[vV]?\ +($NAT)\\.($NAT)(\\.($NAT))?\ +(\\-(${IDENT})(\\.(${IDENT}))*)?\ +(\\+${FIELD}(\\.${FIELD})*)?$" + +SEMVER_REGEX="^$SEMVER_REGEX_STR" + +function error { + echo -e "$1" >&2 + exit 1 +} + +# normalize the "part" keywords to a canonical string. At present, +# only "prerelease" is normalized to "prerel". + +function normalize_part { + if [ "$1" == "prerelease" ]; then + echo "prerel" + else + echo "$1" + fi +} + +function validate_version { + local version=$1 + if [[ "$version" =~ $SEMVER_REGEX ]]; then + # if a second argument is passed, store the result in var named by $2 + if [ "$#" -eq "2" ]; then + local major=${BASH_REMATCH[1]} + local minor=${BASH_REMATCH[2]} + local patch=${BASH_REMATCH[3]} + local prere=${BASH_REMATCH[4]} + local build=${BASH_REMATCH[8]} + eval "$2=(\"$major\" \"$minor\" \"$patch\" \"$prere\" \"$build\")" + else + echo "$version" + fi + elif [[ "$version" =~ $SEMVER_REGEX_LEGACY ]]; then + # if a second argument is passed, store the result in var named by $2 + if [[ "$#" -eq "2" ]]; then + local major=${BASH_REMATCH[1]} + local minor=${BASH_REMATCH[2]} + local patch=0 + local prere=${BASH_REMATCH[4]} + local build=${BASH_REMATCH[6]} + eval "$2=(\"${major}\" \"${minor}\" \"${patch}\" \"${prere}\" \"${build}\")" + else + echo "$version" + fi + else + error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information." + fi +} + +function is_nat { + [[ "$1" =~ ^($NAT)$ ]] +} + +function is_null { + [ -z "$1" ] +} + +function order_nat { + [ "$1" -lt "$2" ] && { + echo -1 + return + } + [ "$1" -gt "$2" ] && { + echo 1 + return + } + echo 0 +} + +function order_string { + [[ $1 < $2 ]] && { + echo -1 + return + } + [[ $1 > $2 ]] && { + echo 1 + return + } + echo 0 +} + +# given two (named) arrays containing NAT and/or ALPHANUM fields, compare them +# one by one according to semver 2.0.0 spec. Return -1, 0, 1 if left array ($1) +# is less-than, equal, or greater-than the right array ($2). The longer array +# is considered greater-than the shorter if the shorter is a prefix of the longer. +# +function compare_fields { + local l="$1[@]" + local r="$2[@]" + local leftfield=("${!l}") + local rightfield=("${!r}") + local left + local right + + local i=$((-1)) + local order=$((0)) + + while true; do + # shellcheck disable=SC2086 + [ $order -ne 0 ] && { + echo "$order" + return + } + + : $((i++)) + left="${leftfield[$i]}" + right="${rightfield[$i]}" + + is_null "$left" && is_null "$right" && { + echo 0 + return + } + is_null "$left" && { + echo -1 + return + } + is_null "$right" && { + echo 1 + return + } + + is_nat "$left" && is_nat "$right" && { + order=$(order_nat "$left" "$right") + continue + } + is_nat "$left" && { + echo -1 + return + } + is_nat "$right" && { + echo 1 + return + } + { + order=$(order_string "$left" "$right") + continue + } + done +} + +# shellcheck disable=SC2206 # checked by "validate"; ok to expand prerel id's into array +function compare_version { + local order + validate_version "$1" V + validate_version "$2" V_ + + # compare major, minor, patch + + local left=("${V[0]}" "${V[1]}" "${V[2]}") + local right=("${V_[0]}" "${V_[1]}" "${V_[2]}") + + order=$(compare_fields left right) + [ "$order" -ne 0 ] && { + echo "$order" + return + } + + # compare pre-release ids when M.m.p are equal + + local prerel="${V[3]:1}" + local prerel_="${V_[3]:1}" + local left=(${prerel//./ }) + local right=(${prerel_//./ }) + + # if left and right have no pre-release part, then left equals right + # if only one of left/right has pre-release part, that one is less than simple M.m.p + + [ -z "$prerel" ] && [ -z "$prerel_" ] && { + echo 0 + return + } + [ -z "$prerel" ] && { + echo 1 + return + } + [ -z "$prerel_" ] && { + echo -1 + return + } + + # otherwise, compare the pre-release id's + + compare_fields left right +} + +# render_prerel -- return a prerel field with a trailing numeric string +# usage: render_prerel numeric [prefix-string] +# +function render_prerel { + if [ -z "$2" ]; then + echo "${1}" + else + echo "${2}${1}" + fi +} + +# extract_prerel -- extract prefix and trailing numeric portions of a pre-release part +# usage: extract_prerel prerel prerel_parts +# The prefix and trailing numeric parts are returned in "prerel_parts". +# +PREFIX_ALPHANUM='[.0-9A-Za-z-]*[.A-Za-z-]' +DIGITS='[0-9][0-9]*' +EXTRACT_REGEX="^(${PREFIX_ALPHANUM})*(${DIGITS})$" + +function extract_prerel { + local prefix + local numeric + + if [[ "$1" =~ $EXTRACT_REGEX ]]; then # found prefix and trailing numeric parts + prefix="${BASH_REMATCH[1]}" + numeric="${BASH_REMATCH[2]}" + else # no numeric part + prefix="${1}" + numeric= + fi + + eval "$2=(\"$prefix\" \"$numeric\")" +} + +# bump_prerel -- return the new pre-release part based on previous pre-release part +# and prototype for bump +# usage: bump_prerel proto previous +# +function bump_prerel { + local proto + local prev_prefix + local prev_numeric + + # case one: no trailing dot in prototype => simply replace previous with proto + if [[ ! ("$1" =~ \.$) ]]; then + echo "$1" + return + fi + + proto="${1%.}" # discard trailing dot marker from prototype + + extract_prerel "${2#-}" prerel_parts # extract parts of previous pre-release + # shellcheck disable=SC2154 + prev_prefix="${prerel_parts[0]}" + prev_numeric="${prerel_parts[1]}" + + # case two: bump or append numeric to previous pre-release part + if [ "$proto" == "+" ]; then # dummy "+" indicates no prototype argument provided + if [ -n "$prev_numeric" ]; then + : $((++prev_numeric)) # previous pre-release is already numbered, bump it + render_prerel "$prev_numeric" "$prev_prefix" + else + render_prerel 1 "$prev_prefix" # append starting number + fi + return + fi + + # case three: set, bump, or append using prototype prefix + if [ "$prev_prefix" != "$proto" ]; then + render_prerel 1 "$proto" # proto not same pre-release; set and start at '1' + elif [ -n "$prev_numeric" ]; then + : $((++prev_numeric)) # pre-release is numbered; bump it + render_prerel "$prev_numeric" "$prev_prefix" + else + render_prerel 1 "$prev_prefix" # start pre-release at number '1' + fi +} + +function command_bump { + local new + local version + local sub_version + local command + + command="$(normalize_part "$1")" + + case $# in + 2) case "$command" in + major | minor | patch | prerel | release) + sub_version="+." + version=$2 + ;; + *) usage_help ;; + esac ;; + 3) case "$command" in + prerel | build) sub_version=$2 version=$3 ;; + *) usage_help ;; + esac ;; + *) usage_help ;; + esac + + validate_version "$version" parts + # shellcheck disable=SC2154 + local major="${parts[0]}" + local minor="${parts[1]}" + local patch="${parts[2]}" + local prere="${parts[3]}" + local build="${parts[4]}" + + case "$command" in + major) new="$((major + 1)).0.0" ;; + minor) new="${major}.$((minor + 1)).0" ;; + patch) new="${major}.${minor}.$((patch + 1))" ;; + release) new="${major}.${minor}.${patch}" ;; + prerel) new=$(validate_version "${major}.${minor}.${patch}-$(bump_prerel "$sub_version" "$prere")") ;; + build) new=$(validate_version "${major}.${minor}.${patch}${prere}+${sub_version}") ;; + *) usage_help ;; + esac + + echo "$new" + exit 0 +} + +function command_compare { + local v + local v_ + + case $# in + 2) + v=$(validate_version "$1") + v_=$(validate_version "$2") + ;; + *) usage_help ;; + esac + + set +u # need unset array element to evaluate to null + compare_version "$v" "$v_" + exit 0 +} + +function command_diff { + validate_version "$1" v1_parts + # shellcheck disable=SC2154 + local v1_major="${v1_parts[0]}" + local v1_minor="${v1_parts[1]}" + local v1_patch="${v1_parts[2]}" + local v1_prere="${v1_parts[3]}" + local v1_build="${v1_parts[4]}" + + validate_version "$2" v2_parts + # shellcheck disable=SC2154 + local v2_major="${v2_parts[0]}" + local v2_minor="${v2_parts[1]}" + local v2_patch="${v2_parts[2]}" + local v2_prere="${v2_parts[3]}" + local v2_build="${v2_parts[4]}" + + if [ "${v1_major}" != "${v2_major}" ]; then + echo "major" + elif [ "${v1_minor}" != "${v2_minor}" ]; then + echo "minor" + elif [ "${v1_patch}" != "${v2_patch}" ]; then + echo "patch" + elif [ "${v1_prere}" != "${v2_prere}" ]; then + echo "prerelease" + elif [ "${v1_build}" != "${v2_build}" ]; then + echo "build" + fi +} + +# shellcheck disable=SC2034 +function command_get { + local part version + + if [[ "$#" -ne "2" ]] || [[ -z "$1" ]] || [[ -z "$2" ]]; then + usage_help + exit 0 + fi + + part="$1" + version="$2" + + validate_version "$version" parts + local major="${parts[0]}" + local minor="${parts[1]}" + local patch="${parts[2]}" + local prerel="${parts[3]:1}" + local build="${parts[4]:1}" + local release="${major}.${minor}.${patch}" + + part="$(normalize_part "$part")" + + case "$part" in + major | minor | patch | release | prerel | build) echo "${!part}" ;; + *) usage_help ;; + esac + + exit 0 +} + +function command_validate { + if [[ "$#" -ne "1" ]]; then + usage_help + fi + + if [[ "$1" =~ $SEMVER_REGEX ]]; then + echo "valid" + else + echo "invalid" + fi + + exit 0 +} diff --git a/script/tools.sh b/script/tools.sh index 5807313c..8b355b67 100755 --- a/script/tools.sh +++ b/script/tools.sh @@ -3,66 +3,93 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" SEMVER=$SCRIPT_DIR/semver.sh +source "$SCRIPT_DIR/semver_funcs.sh" + gomod="$SCRIPT_DIR/../go.mod" function get_gotoolchain() { - local gotoolchain - local goversion - local local_goversion - - gotoolchain=$(grep -E '^toolchain go[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$' < "$gomod" | cut -d ' ' -f 2 | tr -d '\n') - goversion=$(grep -E '^go [0-9]{1,}.[0-9]{1,}(.[0-9]{1,})?$' < "$gomod" | cut -d ' ' -f 2 | tr -d '\n') - - if [[ ${gotoolchain} == "" ]]; then - # determine go toolchain from go version in go.mod - if which go > /dev/null 2>&1 ; then - local_goversion=$(GOTOOLCHAIN=local go version | cut -d ' ' -f 3 | sed 's/go*//' | tr -d '\n') - if [[ $($SEMVER compare "v$local_goversion" v"$goversion") -ge 0 ]]; then - goversion=$local_goversion - else - local_goversion= - fi - fi - - if [[ "$local_goversion" == "" ]]; then - goversion=$(curl -s "https://go.dev/dl/?mode=json&include=all" | jq -r --arg regexp "^go$goversion" '.[] | select(.stable == true) | select(.version | match($regexp)) | .version' | head -n 1 | sed -e s/^go//) - fi - - if [[ $goversion != "" ]] && [[ $($SEMVER compare "v$goversion" v1.21.0) -ge 0 ]]; then - gotoolchain=go${goversion} - else - gotoolchain=go$(grep -E '^go [0-9]{1,}.[0-9]{1,}$' < "$gomod" | cut -d ' ' -f 2 | tr -d '\n').0 - fi - fi - - echo -n "$gotoolchain" + local gotoolchain + local goversion + local local_goversion + + gotoolchain=$(grep -E '^toolchain go[0-9]{1,}.[0-9]{1,}.[0-9]{1,}$' <"$gomod" | cut -d ' ' -f 2 | tr -d '\n') + goversion=$(grep -E '^go [0-9]{1,}.[0-9]{1,}(.[0-9]{1,})?$' <"$gomod" | cut -d ' ' -f 2 | tr -d '\n') + + if [[ ${gotoolchain} == "" ]]; then + # determine go toolchain from go version in go.mod + if which go >/dev/null 2>&1; then + local_goversion=$(GOTOOLCHAIN=local go version | cut -d ' ' -f 3 | sed 's/go*//' | tr -d '\n') + if [[ $($SEMVER compare "v$local_goversion" v"$goversion") -ge 0 ]]; then + goversion=$local_goversion + else + local_goversion= + fi + fi + + if [[ "$local_goversion" == "" ]]; then + goversion=$(curl -s "https://go.dev/dl/?mode=json&include=all" | jq -r --arg regexp "^go$goversion" '.[] | select(.stable == true) | select(.version | match($regexp)) | .version' | head -n 1 | sed -e s/^go//) + fi + + if [[ $goversion != "" ]] && [[ $($SEMVER compare "v$goversion" v1.21.0) -ge 0 ]]; then + gotoolchain=go${goversion} + else + gotoolchain=go$(grep -E '^go [0-9]{1,}.[0-9]{1,}$' <"$gomod" | cut -d ' ' -f 2 | tr -d '\n').0 + fi + fi + + echo -n "$gotoolchain" } function build_akash() { - dev_cache=${AP_DEVCACHE_BIN} - cd "$1" || exit 1 - export AKASH_ROOT="$1" - source .env - make akash AKASH="${dev_cache}/akash" + dev_cache=${AP_DEVCACHE_BIN} + cd "$1" || exit 1 + export AKASH_ROOT="$1" + source .env + make akash AKASH="${dev_cache}/akash" } function build_akash_docker() { - cd "$1" || exit 1 - export AKASH_ROOT="$1" - source .env - make docker-image + cd "$1" || exit 1 + export AKASH_ROOT="$1" + source .env + make docker-image +} + +function run_bump_module() { + local cmd + local prefix + local mod_tag + + cmd="$1" + mod_tag="$(git describe --abbrev=0 --tags --match "v*")" + + if [[ "$mod_tag" =~ $SEMVER_REGEX_STR ]]; then + local nversion + local oversion + + oversion=${BASH_REMATCH[0]} + + nversion=v$($SEMVER bump "$cmd" "$oversion") + git tag -a "$nversion" -m "$nversion" + else + error "unable to find any tag for module $prefix" + fi } case "$1" in -gotoolchain) - get_gotoolchain - ;; -build-akash) - shift - build_akash "$@" - ;; -build-akash-docker) - shift - build_akash_docker "$@" - ;; + gotoolchain) + get_gotoolchain + ;; + build-akash) + shift + build_akash "$@" + ;; + build-akash-docker) + shift + build_akash_docker "$@" + ;; + bump) + shift + run_bump_module "$@" + ;; esac