Skip to content

Commit

Permalink
Relax version checks for snapshot builds (elastic#3039)
Browse files Browse the repository at this point in the history
  • Loading branch information
michel-laterman authored Oct 17, 2023
1 parent 67f9e3d commit cc779a1
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 25 deletions.
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ list-platforms: ## - Show the possible PLATFORMS
.PHONY: local
local: ## - Build local binary for local environment (bin/fleet-server)
@printf "${CMD_COLOR_ON} Build binaries using local go installation\n${CMD_COLOR_OFF}"
go build $(if $(DEV),-tags="dev",) -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" -o ./bin/fleet-server .
go build $(if $(SNAPSHOT),-tags="snapshot",) -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" -o ./bin/fleet-server .
@printf "${CMD_COLOR_ON} Binaries in ./bin/\n${CMD_COLOR_OFF}"

.PHONY: $(COVER_TARGETS)
Expand All @@ -84,7 +84,7 @@ $(COVER_TARGETS): cover-%: ## - Build a binary with the -cover flag for integrat
$(eval $@_GO_ARCH := $(lastword $(subst /, ,$(lastword $(subst cover-, ,$@)))))
$(eval $@_ARCH := $(TARGET_ARCH_$($@_GO_ARCH)))
$(eval $@_BUILDMODE:= $(BUILDMODE_$($@_OS)_$($@_GO_ARCH)))
GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) go build $(if $(DEV),-tags="dev",) -cover -coverpkg=./... -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/cover/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)/fleet-server$(if $(filter windows,$($@_OS)),.exe,) .
GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) go build $(if $(SNAPSHOT),-tags="snapshot",) -cover -coverpkg=./... -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/cover/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)/fleet-server$(if $(filter windows,$($@_OS)),.exe,) .

.PHONY: clean
clean: ## - Clean up build artifacts
Expand Down Expand Up @@ -198,7 +198,7 @@ $(PLATFORM_TARGETS): release-%:
$(eval $@_GO_ARCH := $(lastword $(subst /, ,$(lastword $(subst release-, ,$@)))))
$(eval $@_ARCH := $(TARGET_ARCH_$($@_GO_ARCH)))
$(eval $@_BUILDMODE:= $(BUILDMODE_$($@_OS)_$($@_GO_ARCH)))
GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) go build $(if $(DEV),-tags="dev",) -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/binaries/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)/fleet-server .
GOOS=$($@_OS) GOARCH=$($@_GO_ARCH) go build $(if $(SNAPSHOT),-tags="snapshot",) -gcflags="${GCFLAGS}" -ldflags="${LDFLAGS}" $($@_BUILDMODE) -o build/binaries/fleet-server-$(VERSION)-$($@_OS)-$($@_ARCH)/fleet-server .
@$(MAKE) OS=$($@_OS) ARCH=$($@_ARCH) package-target

.PHONY: build-docker
Expand All @@ -208,6 +208,7 @@ build-docker:
--build-arg=GCFLAGS="${GCFLAGS}" \
--build-arg=LDFLAGS="${LDFLAGS}" \
--build-arg=DEV="$(DEV)" \
--build-arg=SNAPSHOT="$(SNAPSHOT)" \
--build-arg=VERSION="$(VERSION)" \
-t $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG)$(if $(DEV),-dev,) .

Expand All @@ -220,6 +221,7 @@ build-and-push-docker:
--build-arg=GCFLAGS="${GCFLAGS}" \
--build-arg=LDFLAGS="${LDFLAGS}" \
--build-arg=DEV="$(DEV)" \
--build-arg=SNAPSHOT="$(SNAPSHOT)" \
--build-arg=VERSION="$(VERSION)" \
-t $(DOCKER_IMAGE):$(DOCKER_IMAGE_TAG)$(if $(DEV),-dev,) .

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ GOOS=darwin GOARCH=amd64 go build -tags="dev" -gcflags="all=-N -l" -ldflags="-X
Change `release-darwin/amd64` to `release-YOUR_OS/platform`.
Run `make list-platforms` to check out the possible values.

The `SNAPSHOT` flag sets the snapshot version flag.
The `SNAPSHOT` flag sets the snapshot version flag and relaxes client version checks.
When `SNAPSHOT` is set we allow clients of the next version to communicate with fleet-server.
For example, if fleet-server is running version `8.11.0` on a `SNAPSHOT` build, clients can communiate with versions up to `8.12.0`.

### Docker build

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Kind can be one of:
# - breaking-change: a change to previously-documented behavior
# - deprecation: functionality that is being removed in a later release
# - bug-fix: fixes a problem in a previous version
# - enhancement: extends functionality but does not break or fix existing behavior
# - feature: new functionality
# - known-issue: problems that we are aware of in a given version
# - security: impacts on the security of a product or a user’s deployment.
# - upgrade: important information for someone upgrading from a prior version
# - other: does not fit into any of the other categories
kind: enhancement

# Change summary; a 80ish characters long description of the change.
summary: Relax version checks in snapshot builds

# Long description; in case the summary is not enough to describe the change
# this field accommodate a description without length limits.
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
description: |
Relax version checking fleet-server does to client communication when built with SNAPSHOT=true.
Versions allowed will be <=X.Y+1.Z, that is to say snapshots will allow the next minor version to communicate.
This is done to avoid the chicken and egg prpoblem we face in automated testing when releasing new minor versions.
# Affected component; a word indicating the component this changeset affects.
component:

# PR URL; optional; the PR number that added the changeset.
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
# Please provide it if you are adding a fragment for a different PR.
#pr: https://github.com/owner/repo/1234

# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
# If not present is automatically filled by the tooling with the issue linked to the PR number.
issue: 2960
9 changes: 9 additions & 0 deletions internal/pkg/api/handleCheckin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
testcache "github.com/elastic/fleet-server/v7/internal/pkg/testing/cache"
testlog "github.com/elastic/fleet-server/v7/internal/pkg/testing/log"

"github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -578,3 +579,11 @@ func BenchmarkParallel_CheckinT_writeResponse(b *testing.B) {
}
})
}

func mustBuildConstraints(verStr string) version.Constraints {
con, err := BuildVersionConstraint(verStr)
if err != nil {
panic(err)
}
return con
}
12 changes: 0 additions & 12 deletions internal/pkg/api/userAgent.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package api
import (
"context"
"errors"
"fmt"
"math"
"strconv"
"strings"
Expand All @@ -29,17 +28,6 @@ var (
ErrUnsupportedVersion = errors.New("version is not supported")
)

// BuildVersionConstraint turns the version into a constraint to ensure that the connecting Elastic Agent's are
// a supported version.
func BuildVersionConstraint(verStr string) (version.Constraints, error) {
ver, err := version.NewVersion(verStr)
if err != nil {
return nil, err
}
verStr = maximizePatch(ver)
return version.NewConstraint(fmt.Sprintf(">= %s, <= %s", MinVersion, verStr))
}

// maximizePatch turns the version into a string that has the patch value set to the maximum integer.
//
// Used to allow the Elastic Agent to be at a higher patch version than the Fleet Server, but require that the
Expand Down
10 changes: 1 addition & 9 deletions internal/pkg/api/userAgent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

//go:build !integration
//go:build !integration && !snapshot

package api

Expand Down Expand Up @@ -121,11 +121,3 @@ func TestValidateUserAgent(t *testing.T) {
})
}
}

func mustBuildConstraints(verStr string) version.Constraints {
con, err := BuildVersionConstraint(verStr)
if err != nil {
panic(err)
}
return con
}
24 changes: 24 additions & 0 deletions internal/pkg/api/verConst.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

//go:build !snapshot

package api

import (
"fmt"

"github.com/hashicorp/go-version"
)

// BuildVersionConstraint turns the version into a constraint to ensure that the connecting Elastic Agent's are
// a supported version.
func BuildVersionConstraint(verStr string) (version.Constraints, error) {
ver, err := version.NewVersion(verStr)
if err != nil {
return nil, err
}
verStr = maximizePatch(ver)
return version.NewConstraint(fmt.Sprintf(">= %s, <= %s", MinVersion, verStr))
}
41 changes: 41 additions & 0 deletions internal/pkg/api/verConst_snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

//go:build snapshot

package api

import (
"fmt"
"strconv"
"strings"

"github.com/hashicorp/go-version"
)

// BuildVersionConstraint turns the version into a constraint to ensure that the connecting Elastic Agent's are
// a supported version.
// For snapshot builds we allow the minor version to be newer in order to allow automated testing to proceed.
func BuildVersionConstraint(verStr string) (version.Constraints, error) {
ver, err := version.NewVersion(verStr)
if err != nil {
return nil, err
}
verStr = bumpMinor(ver)
return version.NewConstraint(fmt.Sprintf(">= %s, <= %s", MinVersion, verStr))
}

// bumpMinor returns a version string where 1 is added to the minor version
func bumpMinor(ver *version.Version) string {
segments := ver.Segments()
if len(segments) < 2 {
return ver.String()
}
segments[1] += 1
strs := make([]string, 0, len(segments))
for _, seg := range segments {
strs = append(strs, strconv.Itoa(seg))
}
return strings.Join(strs, ".")
}
41 changes: 41 additions & 0 deletions internal/pkg/api/verConst_snapshot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

//go:build !integration && snapshot

package api

import (
"testing"

"github.com/hashicorp/go-version"
"github.com/stretchr/testify/require"
)

func TestVersionConstraint(t *testing.T) {
tests := []struct {
version string
succeed bool
}{{
version: "8.0.0",
succeed: true,
}, {
version: "8.1.0",
succeed: true,
}, {
version: "8.2.0",
succeed: false,
}}

for _, tc := range tests {
t.Run(tc.version, func(t *testing.T) {
vc, err := BuildVersionConstraint("8.0.0")
require.NoError(t, err)
ver, err := version.NewVersion(tc.version)
require.NoError(t, err)

require.Equalf(t, tc.succeed, vc.Check(ver), "vc is %s", vc.String())
})
}
}

0 comments on commit cc779a1

Please sign in to comment.