build: upgrade and speedup circleci configuration
This PR upgrades our CI images and fixes some affected tests. - upgrade go-machine-image to premade latest ubuntu LTS (ubuntu-2004:202111-02) - eliminate go-machine-recent-image (no longer necessary) - manage GOPATH in GNUMakefile (see https://discuss.circleci.com/t/gopath-is-set-to-multiple-directories/7174) - fix tcp dial error check (message seems to be OS specific) - spot check values measured instead of specifically 'RSS' (rss no longer reported in cgroups v2) - use safe MkdirTemp for generating tmpfiles NOT applied: (too flakey) - eliminate setting GOMAXPROCS=1 (build tools were also affected by this setting) - upgrade resource type for all imanges to large (2C -> 4C)
This commit is contained in:
parent
314e907a51
commit
2f0cfb5740
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
build: upgrade and speedup circleci configuration
|
||||||
|
```
|
|
@ -3,9 +3,7 @@ version: 2.1
|
||||||
references:
|
references:
|
||||||
# environment specific references - aim to avoid conflicts
|
# environment specific references - aim to avoid conflicts
|
||||||
go-machine-image: &go_machine_image
|
go-machine-image: &go_machine_image
|
||||||
circleci/classic:201808-01
|
ubuntu-2004:202111-02
|
||||||
go-machine-recent-image: &go_machine_recent_image
|
|
||||||
ubuntu-1604:201903-01
|
|
||||||
go-windows-image: &go_windows_image
|
go-windows-image: &go_windows_image
|
||||||
windows-server-2019-vs2019:stable
|
windows-server-2019-vs2019:stable
|
||||||
|
|
||||||
|
@ -289,7 +287,7 @@ jobs:
|
||||||
default: ""
|
default: ""
|
||||||
executor:
|
executor:
|
||||||
type: string
|
type: string
|
||||||
default: "go-machine-recent"
|
default: "go-machine"
|
||||||
goarch:
|
goarch:
|
||||||
type: string
|
type: string
|
||||||
default: "amd64"
|
default: "amd64"
|
||||||
|
@ -513,6 +511,7 @@ executors:
|
||||||
working_directory: /go/src/github.com/hashicorp/nomad
|
working_directory: /go/src/github.com/hashicorp/nomad
|
||||||
docker:
|
docker:
|
||||||
- image: docker.mirror.hashicorp.services/golang:1.17.5
|
- image: docker.mirror.hashicorp.services/golang:1.17.5
|
||||||
|
resource_class: medium
|
||||||
environment:
|
environment:
|
||||||
<<: *common_envs
|
<<: *common_envs
|
||||||
GOPATH: /go
|
GOPATH: /go
|
||||||
|
@ -521,19 +520,11 @@ executors:
|
||||||
working_directory: ~/go/src/github.com/hashicorp/nomad
|
working_directory: ~/go/src/github.com/hashicorp/nomad
|
||||||
machine:
|
machine:
|
||||||
image: *go_machine_image
|
image: *go_machine_image
|
||||||
|
resource_class: medium
|
||||||
environment: &machine_env
|
environment: &machine_env
|
||||||
<<: *common_envs
|
<<: *common_envs
|
||||||
GOPATH: /home/circleci/go
|
|
||||||
GOLANG_VERSION: 1.17.5
|
GOLANG_VERSION: 1.17.5
|
||||||
|
|
||||||
# uses a more recent image with unattended upgrades disabled properly
|
|
||||||
# but seems to break docker builds
|
|
||||||
go-machine-recent:
|
|
||||||
working_directory: ~/go/src/github.com/hashicorp/nomad
|
|
||||||
machine:
|
|
||||||
image: *go_machine_recent_image
|
|
||||||
environment: *machine_env
|
|
||||||
|
|
||||||
go-macos:
|
go-macos:
|
||||||
working_directory: ~/go/src/github.com/hashicorp/nomad
|
working_directory: ~/go/src/github.com/hashicorp/nomad
|
||||||
macos:
|
macos:
|
||||||
|
@ -636,9 +627,6 @@ workflows:
|
||||||
- test-machine:
|
- test-machine:
|
||||||
name: "test-docker"
|
name: "test-docker"
|
||||||
test_packages: "./drivers/docker"
|
test_packages: "./drivers/docker"
|
||||||
# docker is misbehaving in docker-machine-recent image
|
|
||||||
# and we get unexpected failures
|
|
||||||
# e.g. https://circleci.com/gh/hashicorp/nomad/3854
|
|
||||||
executor: go-machine
|
executor: go-machine
|
||||||
filters: *backend_test_branches_filter
|
filters: *backend_test_branches_filter
|
||||||
- test-machine:
|
- test-machine:
|
||||||
|
|
10
GNUmakefile
10
GNUmakefile
|
@ -8,6 +8,13 @@ GIT_DIRTY := $(if $(shell git status --porcelain),+CHANGES)
|
||||||
|
|
||||||
GO_LDFLAGS := "-X github.com/hashicorp/nomad/version.GitCommit=$(GIT_COMMIT)$(GIT_DIRTY)"
|
GO_LDFLAGS := "-X github.com/hashicorp/nomad/version.GitCommit=$(GIT_COMMIT)$(GIT_DIRTY)"
|
||||||
|
|
||||||
|
ifneq (MSYS_NT,$(THIS_OS))
|
||||||
|
# GOPATH supports PATH style multi-paths; assume the first entry is favorable.
|
||||||
|
# Necessary because new Circle images override GOPATH with multiple values.
|
||||||
|
# See: https://discuss.circleci.com/t/gopath-is-set-to-multiple-directories/7174
|
||||||
|
GOPATH=$(shell go env GOPATH | cut -d: -f1)
|
||||||
|
endif
|
||||||
|
|
||||||
GO_TAGS ?=
|
GO_TAGS ?=
|
||||||
|
|
||||||
ifeq ($(CI),true)
|
ifeq ($(CI),true)
|
||||||
|
@ -241,7 +248,6 @@ tidy:
|
||||||
.PHONY: dev
|
.PHONY: dev
|
||||||
dev: GOOS=$(shell go env GOOS)
|
dev: GOOS=$(shell go env GOOS)
|
||||||
dev: GOARCH=$(shell go env GOARCH)
|
dev: GOARCH=$(shell go env GOARCH)
|
||||||
dev: GOPATH=$(shell go env GOPATH)
|
|
||||||
dev: DEV_TARGET=pkg/$(GOOS)_$(GOARCH)/nomad
|
dev: DEV_TARGET=pkg/$(GOOS)_$(GOARCH)/nomad
|
||||||
dev: hclfmt ## Build for the current development platform
|
dev: hclfmt ## Build for the current development platform
|
||||||
@echo "==> Removing old development build..."
|
@echo "==> Removing old development build..."
|
||||||
|
@ -297,7 +303,7 @@ test-nomad: dev ## Run Nomad test suites
|
||||||
|
|
||||||
.PHONY: test-nomad-module
|
.PHONY: test-nomad-module
|
||||||
test-nomad-module: dev ## Run Nomad test suites on a sub-module
|
test-nomad-module: dev ## Run Nomad test suites on a sub-module
|
||||||
@echo "==> Running Nomad test suites on sub-module:"
|
@echo "==> Running Nomad test suites on sub-module $(GOTEST_MOD)"
|
||||||
@cd $(GOTEST_MOD) && $(if $(ENABLE_RACE),GORACE="strip_path_prefix=$(GOPATH)/src") $(GO_TEST_CMD) \
|
@cd $(GOTEST_MOD) && $(if $(ENABLE_RACE),GORACE="strip_path_prefix=$(GOPATH)/src") $(GO_TEST_CMD) \
|
||||||
$(if $(ENABLE_RACE),-race) $(if $(VERBOSE),-v) \
|
$(if $(ENABLE_RACE),-race) $(if $(VERBOSE),-v) \
|
||||||
-cover \
|
-cover \
|
||||||
|
|
|
@ -72,7 +72,7 @@ func TestCommand_Metrics_Cases(t *testing.T) {
|
||||||
[]string{"-address=http://foo"},
|
[]string{"-address=http://foo"},
|
||||||
1,
|
1,
|
||||||
"",
|
"",
|
||||||
"no such host",
|
"dial tcp: lookup foo: Temporary failure in name resolution",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -425,7 +425,7 @@ func TestExecDriver_Stats(t *testing.T) {
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
select {
|
select {
|
||||||
case stats := <-statsCh:
|
case stats := <-statsCh:
|
||||||
require.NotZero(stats.ResourceUsage.MemoryStats.RSS)
|
require.NotEmpty(stats.ResourceUsage.MemoryStats.Measured)
|
||||||
require.NotZero(stats.Timestamp)
|
require.NotZero(stats.Timestamp)
|
||||||
require.WithinDuration(time.Now(), time.Unix(0, stats.Timestamp), time.Second)
|
require.WithinDuration(time.Now(), time.Unix(0, stats.Timestamp), time.Second)
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
|
|
|
@ -71,6 +71,7 @@ type LibcontainerExecutor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExecutorWithIsolation(logger hclog.Logger) Executor {
|
func NewExecutorWithIsolation(logger hclog.Logger) Executor {
|
||||||
|
|
||||||
logger = logger.Named("isolated_executor")
|
logger = logger.Named("isolated_executor")
|
||||||
if err := shelpers.Init(); err != nil {
|
if err := shelpers.Init(); err != nil {
|
||||||
logger.Error("unable to initialize stats", "error", err)
|
logger.Error("unable to initialize stats", "error", err)
|
||||||
|
|
|
@ -254,7 +254,6 @@ func TestExecutor_WaitExitSignal(pt *testing.T) {
|
||||||
pt.Parallel()
|
pt.Parallel()
|
||||||
for name, factory := range executorFactories {
|
for name, factory := range executorFactories {
|
||||||
pt.Run(name, func(t *testing.T) {
|
pt.Run(name, func(t *testing.T) {
|
||||||
require := require.New(t)
|
|
||||||
testExecCmd := testExecutorCommand(t)
|
testExecCmd := testExecutorCommand(t)
|
||||||
execCmd, allocDir := testExecCmd.command, testExecCmd.allocDir
|
execCmd, allocDir := testExecCmd.command, testExecCmd.allocDir
|
||||||
execCmd.Cmd = "/bin/sleep"
|
execCmd.Cmd = "/bin/sleep"
|
||||||
|
@ -266,8 +265,8 @@ func TestExecutor_WaitExitSignal(pt *testing.T) {
|
||||||
executor := factory.new(testlog.HCLogger(t))
|
executor := factory.new(testlog.HCLogger(t))
|
||||||
defer executor.Shutdown("", 0)
|
defer executor.Shutdown("", 0)
|
||||||
|
|
||||||
ps, err := executor.Launch(execCmd)
|
pState, err := executor.Launch(execCmd)
|
||||||
require.NoError(err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
tu.WaitForResult(func() (bool, error) {
|
tu.WaitForResult(func() (bool, error) {
|
||||||
|
@ -280,10 +279,14 @@ func TestExecutor_WaitExitSignal(pt *testing.T) {
|
||||||
return false, fmt.Errorf("stats failed to send on interval")
|
return false, fmt.Errorf("stats failed to send on interval")
|
||||||
case ru := <-ch:
|
case ru := <-ch:
|
||||||
assert.NotEmpty(t, ru.Pids, "no pids recorded in stats")
|
assert.NotEmpty(t, ru.Pids, "no pids recorded in stats")
|
||||||
assert.NotZero(t, ru.ResourceUsage.MemoryStats.RSS)
|
|
||||||
|
// just checking we measured something; each executor type has its own abilities,
|
||||||
|
// and e.g. cgroup v2 provides different information than cgroup v1
|
||||||
|
assert.NotEmpty(t, ru.ResourceUsage.MemoryStats.Measured)
|
||||||
|
|
||||||
assert.WithinDuration(t, time.Now(), time.Unix(0, ru.Timestamp), time.Second)
|
assert.WithinDuration(t, time.Now(), time.Unix(0, ru.Timestamp), time.Second)
|
||||||
}
|
}
|
||||||
proc, err := os.FindProcess(ps.Pid)
|
proc, err := os.FindProcess(pState.Pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -298,9 +301,9 @@ func TestExecutor_WaitExitSignal(pt *testing.T) {
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ps, err = executor.Wait(context.Background())
|
pState, err = executor.Wait(context.Background())
|
||||||
require.NoError(err)
|
require.NoError(t, err)
|
||||||
require.Equal(ps.Signal, int(syscall.SIGKILL))
|
require.Equal(t, pState.Signal, int(syscall.SIGKILL))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,32 +12,37 @@ import (
|
||||||
|
|
||||||
func TestWait_WaitForFilesUntil(t *testing.T) {
|
func TestWait_WaitForFilesUntil(t *testing.T) {
|
||||||
|
|
||||||
var files []string
|
N := 10
|
||||||
for i := 1; i < 10; i++ {
|
|
||||||
filename := fmt.Sprintf("test%d.txt", i)
|
|
||||||
filepath := filepath.Join(os.TempDir(), filename)
|
|
||||||
files = append(files, filepath)
|
|
||||||
|
|
||||||
defer os.Remove(filepath)
|
tmpDir, err := os.MkdirTemp("", "waiter")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
require.NoError(t, os.RemoveAll(tmpDir))
|
||||||
|
}()
|
||||||
|
|
||||||
|
var files []string
|
||||||
|
for i := 1; i < N; i++ {
|
||||||
|
files = append(files, filepath.Join(
|
||||||
|
tmpDir, fmt.Sprintf("test%d.txt", i),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for _, filepath := range files {
|
for _, file := range files {
|
||||||
t.Logf("Creating file %s...", filepath)
|
t.Logf("Creating file %s ...", file)
|
||||||
fh, err := os.Create(filepath)
|
fh, createErr := os.Create(file)
|
||||||
fh.Close()
|
require.NoError(t, createErr)
|
||||||
|
|
||||||
require.NoError(t, err, "error creating test file")
|
closeErr := fh.Close()
|
||||||
require.FileExists(t, filepath)
|
require.NoError(t, closeErr)
|
||||||
|
require.FileExists(t, file)
|
||||||
|
|
||||||
time.Sleep(250 * time.Millisecond)
|
time.Sleep(250 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
duration := 5 * time.Second
|
duration := 5 * time.Second
|
||||||
t.Log("Waiting 5 seconds for files...")
|
t.Log("Waiting 5 seconds for files ...")
|
||||||
WaitForFilesUntil(t, files, duration)
|
WaitForFilesUntil(t, files, duration)
|
||||||
|
|
||||||
t.Log("done")
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue