Compare commits

..

1 Commits

Author SHA1 Message Date
blink-so[bot] 26c933f813 test: Add test file from Blink 2026-01-06 18:17:33 +00:00
825 changed files with 6114 additions and 17626 deletions
+4 -2
View File
@@ -7,6 +7,8 @@ runs:
- name: go install tools
shell: bash
run: |
go install tool
# NOTE: protoc-gen-go cannot be installed with `go get`
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.30
go install storj.io/drpc/cmd/protoc-gen-go-drpc@v0.0.34
go install golang.org/x/tools/cmd/goimports@v0.31.0
go install github.com/mikefarah/yq/v4@v4.44.3
go install go.uber.org/mock/mockgen@v0.5.0
-1
View File
@@ -71,7 +71,6 @@ runs:
if [[ ${RACE_DETECTION} == true ]]; then
gotestsum --junitfile="gotests.xml" --packages="${TEST_PACKAGES}" -- \
-tags=testsmallbatch \
-race \
-parallel "${TEST_NUM_PARALLEL_TESTS}" \
-p "${TEST_NUM_PARALLEL_PACKAGES}"
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
# on version 2.29 and above.
nix_version: "2.28.5"
- uses: nix-community/cache-nix-action@b426b118b6dc86d6952988d396aa7c6b09776d08 # v7.0.0
- uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6.1.3
with:
# restore and save a cache using this key
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
+1 -1
View File
@@ -20,4 +20,4 @@ jobs:
egress-policy: audit
- name: Assign author
uses: toshimaru/auto-author-assign@4d585cc37690897bd9015942ed6e766aa7cdb97f # v3.0.1
uses: toshimaru/auto-author-assign@16f0022cf3d7970c106d8d1105f75a1165edb516 # v2.1.1
-1
View File
@@ -3,7 +3,6 @@
.eslintcache
.gitpod.yml
.idea
.run
**/*.swp
gotests.coverage
gotests.xml
-8
View File
@@ -211,14 +211,6 @@ issues:
- path: scripts/rules.go
linters:
- ALL
# Boundary code is imported from github.com/coder/boundary and has different
# lint standards. Suppress lint issues in this imported code.
- path: enterprise/cli/boundary/
linters:
- revive
- gocritic
- gosec
- errorlint
fix: true
max-issues-per-linter: 0
+6 -17
View File
@@ -464,7 +464,7 @@ ifdef FILE
# Format single file
if [[ -f "$(FILE)" ]] && [[ "$(FILE)" == *.go ]] && ! grep -q "DO NOT EDIT" "$(FILE)"; then \
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/go$(RESET) $(FILE)"; \
./scripts/format_go_file.sh "$(FILE)"; \
go run mvdan.cc/gofumpt@v0.8.0 -w -l "$(FILE)"; \
fi
else
go mod tidy
@@ -473,7 +473,7 @@ else
# https://github.com/mvdan/gofumpt#visual-studio-code
find . $(FIND_EXCLUSIONS) -type f -name '*.go' -print0 | \
xargs -0 grep -E --null -L '^// Code generated .* DO NOT EDIT\.$$' | \
xargs -0 ./scripts/format_go_file.sh
xargs -0 go run mvdan.cc/gofumpt@v0.8.0 -w -l
endif
.PHONY: fmt/go
@@ -578,7 +578,7 @@ lint/go:
./scripts/check_codersdk_imports.sh
linter_ver=$(shell egrep -o 'GOLANGCI_LINT_VERSION=\S+' dogfood/coder/Dockerfile | cut -d '=' -f 2)
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v$$linter_ver run
go tool github.com/coder/paralleltestctx/cmd/paralleltestctx -custom-funcs="testutil.Context" ./...
go run github.com/coder/paralleltestctx/cmd/paralleltestctx@v0.0.1 -custom-funcs="testutil.Context" ./...
.PHONY: lint/go
lint/examples:
@@ -604,7 +604,7 @@ lint/actions: lint/actions/actionlint lint/actions/zizmor
.PHONY: lint/actions
lint/actions/actionlint:
go tool github.com/rhysd/actionlint/cmd/actionlint
go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7
.PHONY: lint/actions/actionlint
lint/actions/zizmor:
@@ -1018,8 +1018,7 @@ endif
# default to 8x8 parallelism to avoid overwhelming our workspaces. Hopefully we can remove these defaults
# when we get our test suite's resource utilization under control.
# Use testsmallbatch tag to reduce wireguard memory allocation in tests (from ~18GB to negligible).
GOTEST_FLAGS := -tags=testsmallbatch -v -p $(or $(TEST_NUM_PARALLEL_PACKAGES),"8") -parallel=$(or $(TEST_NUM_PARALLEL_TESTS),"8")
GOTEST_FLAGS := -v -p $(or $(TEST_NUM_PARALLEL_PACKAGES),"8") -parallel=$(or $(TEST_NUM_PARALLEL_TESTS),"8")
# The most common use is to set TEST_COUNT=1 to avoid Go's test cache.
ifdef TEST_COUNT
@@ -1034,14 +1033,6 @@ ifdef RUN
GOTEST_FLAGS += -run $(RUN)
endif
ifdef TEST_CPUPROFILE
GOTEST_FLAGS += -cpuprofile=$(TEST_CPUPROFILE)
endif
ifdef TEST_MEMPROFILE
GOTEST_FLAGS += -memprofile=$(TEST_MEMPROFILE)
endif
TEST_PACKAGES ?= ./...
test:
@@ -1090,7 +1081,6 @@ test-postgres: test-postgres-docker
--jsonfile="gotests.json" \
$(GOTESTSUM_RETRY_FLAGS) \
--packages="./..." -- \
-tags=testsmallbatch \
-timeout=20m \
-count=1
.PHONY: test-postgres
@@ -1163,7 +1153,7 @@ test-postgres-docker:
# Make sure to keep this in sync with test-go-race from .github/workflows/ci.yaml.
test-race:
$(GIT_FLAGS) gotestsum --junitfile="gotests.xml" -- -tags=testsmallbatch -race -count=1 -parallel 4 -p 4 ./...
$(GIT_FLAGS) gotestsum --junitfile="gotests.xml" -- -race -count=1 -parallel 4 -p 4 ./...
.PHONY: test-race
test-tailnet-integration:
@@ -1173,7 +1163,6 @@ test-tailnet-integration:
TS_DEBUG_NETCHECK=true \
GOTRACEBACK=single \
go test \
-tags=testsmallbatch \
-exec "sudo -E" \
-timeout=5m \
-count=1 \
+1
View File
@@ -0,0 +1 @@
# Test PR from Blink
+1 -1
View File
@@ -36,7 +36,7 @@ import (
"tailscale.com/types/netlogtype"
"tailscale.com/util/clientmetric"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/clistat"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentexec"
+3 -2
View File
@@ -6,8 +6,9 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/testutil"
)
+7 -5
View File
@@ -25,6 +25,10 @@ import (
"testing"
"time"
"go.uber.org/goleak"
"tailscale.com/net/speedtest"
"tailscale.com/tailcfg"
"github.com/bramvdbogaerde/go-scp"
"github.com/google/uuid"
"github.com/ory/dockertest/v3"
@@ -36,14 +40,12 @@ import (
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/goleak"
"golang.org/x/crypto/ssh"
"golang.org/x/xerrors"
"tailscale.com/net/speedtest"
"tailscale.com/tailcfg"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentssh"
+1 -1
View File
@@ -26,7 +26,7 @@ import (
"github.com/spf13/afero"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentcontainers/ignore"
"github.com/coder/coder/v2/agent/agentcontainers/watcher"
"github.com/coder/coder/v2/agent/agentexec"
+3 -3
View File
@@ -27,9 +27,9 @@ import (
"go.uber.org/mock/gomock"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentcontainers/acmock"
"github.com/coder/coder/v2/agent/agentcontainers/watcher"
+2 -1
View File
@@ -10,10 +10,11 @@ package dcspec
import (
"bytes"
"encoding/json"
"errors"
)
import "encoding/json"
func UnmarshalDevContainer(data []byte) (DevContainer, error) {
var r DevContainer
err := json.Unmarshal(data, &r)
+1 -1
View File
@@ -61,7 +61,7 @@ fi
exec 3>&-
# Format the generated code.
"${PROJECT_ROOT}/scripts/format_go_file.sh" "${TMPDIR}/${DEST_FILENAME}"
go run mvdan.cc/gofumpt@v0.8.0 -w -l "${TMPDIR}/${DEST_FILENAME}"
# Add a header so that Go recognizes this as a generated file.
if grep -q -- "\[-i extension\]" < <(sed -h 2>&1); then
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/google/uuid"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/codersdk"
)
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/codersdk"
)
@@ -21,8 +21,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/codersdk"
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"runtime"
"strings"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/agent/usershell"
"github.com/coder/coder/v2/pty"
+1 -1
View File
@@ -14,7 +14,7 @@ import (
"github.com/spf13/afero"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
const (
+2 -1
View File
@@ -7,7 +7,8 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/codersdk"
)
+2 -1
View File
@@ -20,7 +20,8 @@ import (
"golang.org/x/xerrors"
"google.golang.org/protobuf/types/known/timestamppb"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/coderd/database/dbtime"
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"os/exec"
"syscall"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
func cmdSysProcAttr() *syscall.SysProcAttr {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"os/exec"
"syscall"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
func cmdSysProcAttr() *syscall.SysProcAttr {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"storj.io/drpc/drpcmux"
"storj.io/drpc/drpcserver"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentsocket/proto"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/codersdk/drpcsdk"
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/agenttest"
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentsocket/proto"
"github.com/coder/coder/v2/agent/unit"
)
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/testutil"
+2 -1
View File
@@ -27,7 +27,8 @@ import (
gossh "golang.org/x/crypto/ssh"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/agent/agentrsa"
+3 -2
View File
@@ -24,8 +24,9 @@ import (
"go.uber.org/goleak"
"golang.org/x/crypto/ssh"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/pty/ptytest"
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"os"
"syscall"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
func cmdSysProcAttr() *syscall.SysProcAttr {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"os"
"syscall"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
func cmdSysProcAttr() *syscall.SysProcAttr {
+1 -1
View File
@@ -15,7 +15,7 @@ import (
gossh "golang.org/x/crypto/ssh"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
// streamLocalForwardPayload describes the extra data sent in a
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"go.uber.org/atomic"
gossh "golang.org/x/crypto/ssh"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
// localForwardChannelData is copied from the ssh package.
+1 -1
View File
@@ -21,7 +21,7 @@ import (
gossh "golang.org/x/crypto/ssh"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
const (
+1 -1
View File
@@ -21,7 +21,7 @@ import (
"storj.io/drpc/drpcserver"
"tailscale.com/tailcfg"
"cdr.dev/slog/v3"
"cdr.dev/slog"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/quartz"
+2 -1
View File
@@ -14,7 +14,8 @@ import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/boundarylogproxy"
"github.com/coder/coder/v2/agent/boundarylogproxy/codec"
agentproto "github.com/coder/coder/v2/agent/proto"
+1 -1
View File
@@ -14,7 +14,7 @@ import (
"golang.org/x/xerrors"
"google.golang.org/protobuf/proto"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/boundarylogproxy/codec"
agentproto "github.com/coder/coder/v2/agent/proto"
)
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"runtime"
"sync"
"cdr.dev/slog/v3"
"cdr.dev/slog"
)
// checkpoint allows a goroutine to communicate when it is OK to proceed beyond some async condition
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/testutil"
)
+1 -1
View File
@@ -17,7 +17,7 @@ import (
"golang.org/x/text/transform"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/workspacesdk"
+1 -1
View File
@@ -9,7 +9,7 @@ import (
prompb "github.com/prometheus/client_model/go"
"tailscale.com/util/clientmetric"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/proto"
)
+2 -3
View File
@@ -4538,9 +4538,8 @@ type BoundaryLog_HttpRequest struct {
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
// The rule that resulted in this HTTP request being allowed. Only populated
// when allowed = true because boundary denies requests by default and
// requires rule(s) that allow requests.
// The rule that resulted in this HTTP request not being allowed.
// Only populated when allowed = false.
MatchedRule string `protobuf:"bytes,3,opt,name=matched_rule,json=matchedRule,proto3" json:"matched_rule,omitempty"`
}
+2 -3
View File
@@ -466,9 +466,8 @@ message BoundaryLog {
message HttpRequest {
string method = 1;
string url = 2;
// The rule that resulted in this HTTP request being allowed. Only populated
// when allowed = true because boundary denies requests by default and
// requires rule(s) that allow requests.
// The rule that resulted in this HTTP request not being allowed.
// Only populated when allowed = false.
string matched_rule = 3;
}
@@ -4,7 +4,7 @@ import (
"context"
"time"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/proto"
"github.com/coder/quartz"
)
@@ -8,8 +8,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/agent/proto/resourcesmonitor"
"github.com/coder/quartz"
+2 -1
View File
@@ -12,7 +12,8 @@ import (
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/pty"
)
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/coder/v2/pty"
+1 -1
View File
@@ -18,7 +18,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/pty"
)
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/agent/usershell"
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"golang.org/x/xerrors"
"tailscale.com/types/netlogtype"
"cdr.dev/slog/v3"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/proto"
)
+1
View File
@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/durationpb"
"tailscale.com/types/ipproto"
"tailscale.com/types/netlogtype"
"github.com/coder/coder/v2/agent/proto"
+8 -6
View File
@@ -16,14 +16,17 @@ import (
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/xerrors"
"gopkg.in/natefinch/lumberjack.v2"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog/v3/sloggers/slogjson"
"cdr.dev/slog/v3/sloggers/slogstackdriver"
"github.com/prometheus/client_golang/prometheus"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogjson"
"cdr.dev/slog/sloggers/slogstackdriver"
"github.com/coder/serpent"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentexec"
@@ -34,7 +37,6 @@ import (
"github.com/coder/coder/v2/cli/clilog"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/serpent"
)
func workspaceAgent() *serpent.Command {
+4 -4
View File
@@ -11,10 +11,10 @@ import (
"golang.org/x/xerrors"
"gopkg.in/natefinch/lumberjack.v2"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog/v3/sloggers/slogjson"
"cdr.dev/slog/v3/sloggers/slogstackdriver"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogjson"
"cdr.dev/slog/sloggers/slogstackdriver"
"github.com/coder/coder/v2/coderd/tracing"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
+3 -3
View File
@@ -7,13 +7,13 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clilog"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBuilder(t *testing.T) {
+2 -2
View File
@@ -17,8 +17,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/cli"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/codersdk"
+2 -1
View File
@@ -13,11 +13,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/coder/coder/v2/testutil"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/serpent"
)
+2 -1
View File
@@ -22,9 +22,10 @@ import (
"golang.org/x/exp/constraints"
"golang.org/x/xerrors"
"github.com/coder/serpent"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
)
const (
+2 -1
View File
@@ -1,8 +1,9 @@
package cli
import (
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/serpent"
"github.com/coder/coder/v2/codersdk/workspacesdk"
)
func (r *RootCmd) connectCmd() *serpent.Command {
+2 -1
View File
@@ -9,10 +9,11 @@ import (
"github.com/stretchr/testify/require"
"tailscale.com/net/tsaddr"
"github.com/coder/serpent"
"github.com/coder/coder/v2/cli"
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/coder/v2/testutil"
"github.com/coder/serpent"
)
func TestConnectExists_Running(t *testing.T) {
+2 -1
View File
@@ -12,12 +12,13 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/coder/pretty"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/cliutil"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/coderd/util/slice"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
)
+6 -4
View File
@@ -10,21 +10,23 @@ import (
"time"
"github.com/google/uuid"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/pubsub"
"github.com/coder/quartz"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/database/pubsub"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/quartz"
)
func TestDelete(t *testing.T) {
+2 -1
View File
@@ -13,8 +13,9 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/pretty"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/serpent"
)
+4 -10
View File
@@ -1,18 +1,12 @@
package cli
import (
"golang.org/x/xerrors"
boundarycli "github.com/coder/boundary/cli"
"github.com/coder/serpent"
)
func (*RootCmd) boundary() *serpent.Command {
return &serpent.Command{
Use: "boundary",
Short: "Network isolation tool for monitoring and restricting HTTP/HTTPS requests (enterprise)",
Long: `boundary creates an isolated network environment for target processes. This is an enterprise feature.`,
Handler: func(_ *serpent.Invocation) error {
return xerrors.New("boundary is an enterprise feature; upgrade to use this command")
},
}
cmd := boundarycli.BaseCommand() // Package coder/boundary/cli exports a "base command" designed to be integrated as a subcommand.
cmd.Use += " [args...]" // The base command looks like `boundary -- command`. Serpent adds the flags piece, but we need to add the args.
return cmd
}
+7 -3
View File
@@ -5,13 +5,15 @@ import (
"github.com/stretchr/testify/assert"
boundarycli "github.com/coder/boundary/cli"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
// Here we want to test that integrating boundary as a subcommand doesn't break anything.
// The full boundary functionality is tested in enterprise/cli.
// Actually testing the functionality of coder/boundary takes place in the
// coder/boundary repo, since it's a dependency of coder.
// Here we want to test basically that integrating it as a subcommand doesn't break anything.
func TestBoundarySubcommand(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
@@ -25,5 +27,7 @@ func TestBoundarySubcommand(t *testing.T) {
}()
// Expect the --help output to include the short description.
pty.ExpectMatch("Network isolation tool")
// We're simply confirming that `coder boundary --help` ran without a runtime error as
// a good chunk of serpents self validation logic happens at runtime.
pty.ExpectMatch(boundarycli.BaseCommand().Short)
}
+3 -2
View File
@@ -7,8 +7,6 @@ import (
"github.com/google/uuid"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentcontainers"
@@ -17,6 +15,9 @@ import (
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestExpRpty(t *testing.T) {
+3 -2
View File
@@ -24,8 +24,9 @@ import (
"go.opentelemetry.io/otel/trace"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/coderd/tracing"
+6 -4
View File
@@ -10,12 +10,14 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/serpent"
"github.com/coder/coder/v2/scaletest/dynamicparameters"
"github.com/coder/coder/v2/scaletest/harness"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"github.com/coder/serpent"
)
const (
+4 -2
View File
@@ -18,12 +18,14 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"cdr.dev/slog"
notificationsLib "github.com/coder/coder/v2/coderd/notifications"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/scaletest/createusers"
"github.com/coder/coder/v2/scaletest/harness"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"github.com/coder/coder/v2/scaletest/notifications"
"github.com/coder/serpent"
)
+2 -1
View File
@@ -13,9 +13,10 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/scaletest/harness"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"github.com/coder/coder/v2/scaletest/prebuilds"
"github.com/coder/quartz"
"github.com/coder/serpent"
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/scaletest/smtpmock"
"github.com/coder/serpent"
)
+6 -4
View File
@@ -14,13 +14,15 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/serpent"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/scaletest/harness"
"github.com/coder/coder/v2/scaletest/loadtestutil"
"github.com/coder/coder/v2/scaletest/taskstatus"
"github.com/coder/serpent"
)
const (
+2 -1
View File
@@ -7,7 +7,8 @@ import (
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/require"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
+2 -2
View File
@@ -4,12 +4,12 @@ import (
"bytes"
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbfake"
"github.com/stretchr/testify/require"
)
func TestFavoriteUnfavorite(t *testing.T) {
+2 -1
View File
@@ -16,11 +16,12 @@ import (
"github.com/pkg/browser"
"golang.org/x/xerrors"
"github.com/coder/pretty"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/sessionstore"
"github.com/coder/coder/v2/coderd/userpassword"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
)
+2 -1
View File
@@ -11,13 +11,14 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/pretty"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
"github.com/coder/pretty"
)
func TestLogin(t *testing.T) {
-270
View File
@@ -1,270 +0,0 @@
package cli
import (
"context"
"fmt"
"slices"
"strconv"
"strings"
"time"
"github.com/google/uuid"
"golang.org/x/sync/errgroup"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
)
func (r *RootCmd) logs() *serpent.Command {
var (
buildNumberArg int64
followArg bool
)
cmd := &serpent.Command{
Use: "logs <workspace>",
Short: "View logs for a workspace",
Long: "View logs for a workspace",
Middleware: serpent.Chain(
serpent.RequireNArgs(1),
),
Options: serpent.OptionSet{
{
Name: "Build Number",
Flag: "build-number",
FlagShorthand: "n",
Description: "Only show logs for a specific build number. Defaults to 0, which maps to the most recent build (build numbers start at 1). Negative values are treated as offsets—for example, -1 refers to the previous build.",
Value: serpent.Int64Of(&buildNumberArg),
Default: "0",
},
{
Name: "Follow",
Flag: "follow",
FlagShorthand: "f",
Description: "Follow logs as they are emitted.",
Value: serpent.BoolOf(&followArg),
Default: "false",
},
},
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
client, err := r.InitClient(inv)
if err != nil {
return err
}
ws, err := namedWorkspace(inv.Context(), client, inv.Args[0])
if err != nil {
return xerrors.Errorf("failed to get workspace: %w", err)
}
bld := ws.LatestBuild
buildNumber := buildNumberArg
// User supplied a negative build number, treat it as an offset from the latest build
if buildNumber < 0 {
buildNumber = int64(ws.LatestBuild.BuildNumber) + buildNumberArg
if buildNumber < 1 {
return xerrors.Errorf("invalid build number offset: %d latest build number: %d", buildNumberArg, ws.LatestBuild.BuildNumber)
}
}
// Fetch specific build if requested
if buildNumber > 0 {
wb, err := client.WorkspaceBuildByUsernameAndWorkspaceNameAndBuildNumber(ctx, ws.OwnerName, ws.Name, strconv.FormatInt(buildNumber, 10))
if err != nil {
return xerrors.Errorf("failed to get build %d: %w", buildNumberArg, err)
}
bld = wb
}
cliui.Infof(inv.Stdout, "--- Logs for workspace build #%d (ID: %s Template Version: %s) ---", bld.BuildNumber, bld.ID, bld.TemplateVersionName)
logs, logsCh, err := workspaceLogs(ctx, client, bld, followArg)
if err != nil {
return err
}
for _, log := range logs {
_, _ = fmt.Fprintln(inv.Stdout, log.String())
}
if followArg {
_, _ = fmt.Fprintln(inv.Stdout, "--- Streaming logs ---")
for log := range logsCh {
_, _ = fmt.Fprintln(inv.Stdout, log.String())
}
}
return nil
},
}
return cmd
}
type logLine struct {
ts time.Time
Content string
}
func (l *logLine) String() string {
var sb strings.Builder
_, _ = sb.WriteString(l.ts.Format(time.RFC3339))
_, _ = sb.WriteString(l.Content)
return sb.String()
}
// workspaceLogs fetches logs for the given workspace build. If follow is true,
// the returned channel will stream new logs as they are emitted. Otherwise,
// the channel will be closed immediately.
// nolint: revive // control flag is appropriate here
func workspaceLogs(ctx context.Context, client *codersdk.Client, wb codersdk.WorkspaceBuild, follow bool) ([]logLine, <-chan logLine, error) {
logs := make([]logLine, 0)
logsCh := make(chan logLine)
followCh := make(chan logLine)
var fetchGroup, followGroup errgroup.Group
buildLogsAfterCh := make(chan int64)
fetchGroup.Go(func() error {
var afterID int64
defer func() {
if !follow {
return
}
buildLogsAfterCh <- afterID
}()
buildLogsC, closer, err := client.WorkspaceBuildLogsAfter(ctx, wb.ID, 0)
if err != nil {
return xerrors.Errorf("failed to get build logs: %w", err)
}
defer closer.Close()
for log := range buildLogsC {
afterID = log.ID
logsCh <- logLine{
ts: log.CreatedAt,
Content: buildLogToString(log),
}
}
return nil
})
if follow {
followGroup.Go(func() error {
afterID := <-buildLogsAfterCh
buildLogsC, closer, err := client.WorkspaceBuildLogsAfter(ctx, wb.ID, afterID)
if err != nil {
return xerrors.Errorf("failed to follow build logs: %w", err)
}
defer closer.Close()
for log := range buildLogsC {
followCh <- logLine{
ts: log.CreatedAt,
Content: buildLogToString(log),
}
}
return nil
})
}
for _, res := range wb.Resources {
for _, agt := range res.Agents {
logSrcNames := make(map[uuid.UUID]string)
for _, src := range agt.LogSources {
logSrcNames[src.ID] = src.DisplayName
}
agentLogsAfterCh := make(chan int64)
var afterID int64
fetchGroup.Go(func() error {
defer func() {
if !follow {
return
}
agentLogsAfterCh <- afterID
}()
agentLogsCh, closer, err := client.WorkspaceAgentLogsAfter(ctx, agt.ID, 0, false)
if err != nil {
return xerrors.Errorf("failed to get agent logs: %w", err)
}
defer closer.Close()
for logChunk := range agentLogsCh {
for _, log := range logChunk {
afterID = log.ID
logsCh <- logLine{
ts: log.CreatedAt,
Content: workspaceAgentLogToString(log, agt.Name, logSrcNames[log.SourceID]),
}
}
}
return nil
})
if follow {
followGroup.Go(func() error {
afterID := <-agentLogsAfterCh
agentLogsCh, closer, err := client.WorkspaceAgentLogsAfter(ctx, agt.ID, afterID, true)
if err != nil {
return xerrors.Errorf("failed to follow agent logs: %w", err)
}
defer closer.Close()
for logChunk := range agentLogsCh {
for _, log := range logChunk {
followCh <- logLine{
ts: log.CreatedAt,
Content: workspaceAgentLogToString(log, agt.Name, logSrcNames[log.SourceID]),
}
}
}
return nil
})
}
}
}
logsDone := make(chan struct{})
go func() {
defer close(logsDone)
for log := range logsCh {
logs = append(logs, log)
}
}()
err := fetchGroup.Wait()
close(logsCh)
<-logsDone
slices.SortFunc(logs, func(a, b logLine) int {
return a.ts.Compare(b.ts)
})
if follow {
go func() {
_ = followGroup.Wait()
close(followCh)
}()
} else {
close(followCh)
}
return logs, followCh, err
}
func buildLogToString(log codersdk.ProvisionerJobLog) string {
var sb strings.Builder
_, _ = sb.WriteString(" [")
_, _ = sb.WriteString(string(log.Level))
_, _ = sb.WriteString("] [")
_, _ = sb.WriteString("provisioner|")
_, _ = sb.WriteString(log.Stage)
_, _ = sb.WriteString("] ")
_, _ = sb.WriteString(log.Output)
return sb.String()
}
func workspaceAgentLogToString(log codersdk.WorkspaceAgentLog, agtName, srcName string) string {
var sb strings.Builder
_, _ = sb.WriteString(" [")
_, _ = sb.WriteString(string(log.Level))
_, _ = sb.WriteString("] [")
_, _ = sb.WriteString("agent.")
_, _ = sb.WriteString(agtName)
_, _ = sb.WriteString("|")
_, _ = sb.WriteString(srcName)
_, _ = sb.WriteString("] ")
_, _ = sb.WriteString(log.Output)
return sb.String()
}
-115
View File
@@ -1,115 +0,0 @@
package cli_test
import (
"fmt"
"strings"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbfake"
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/testutil"
)
func TestLogsCmd(t *testing.T) {
t.Parallel()
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{})
owner := coderdtest.CreateFirstUser(t, client)
memberClient, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
testWorkspace := func(t testing.TB, db database.Store, ownerID, orgID uuid.UUID) dbfake.WorkspaceResponse {
wb := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OwnerID: memberUser.ID,
OrganizationID: owner.OrganizationID,
}).WithAgent().Do()
_ = dbgen.ProvisionerJobLog(t, db, database.ProvisionerJobLog{
JobID: wb.Build.JobID,
Output: "test provisioner log for build " + wb.Build.ID.String(),
})
for _, agt := range wb.Agents {
_ = dbgen.WorkspaceAgentLog(t, db, database.WorkspaceAgentLog{
AgentID: agt.ID,
Output: "test agent log for agent " + agt.ID.String(),
})
}
return wb
}
assertLogOutput := func(t testing.TB, wb dbfake.WorkspaceResponse, output string) {
t.Helper()
require.Contains(t, output, "test provisioner log for build "+wb.Build.ID.String())
for _, agt := range wb.Agents {
require.Contains(t, output, "test agent log for agent "+agt.ID.String())
}
}
assertAntagonist := func(t testing.TB, wb dbfake.WorkspaceResponse, output string) {
t.Helper()
require.NotContains(t, output, "test provisioner log for build "+wb.Build.ID.String())
for _, agt := range wb.Agents {
require.NotContains(t, output, "test agent log for agent "+agt.ID.String())
}
}
wb1 := testWorkspace(t, db, memberUser.ID, owner.OrganizationID)
wb2 := testWorkspace(t, db, owner.UserID, owner.OrganizationID)
t.Run("workspace not found", func(t *testing.T) {
t.Parallel()
inv, root := clitest.New(t, "logs", "doesnotexist")
clitest.SetupConfig(t, memberClient, root)
ctx := testutil.Context(t, testutil.WaitShort)
var stdout strings.Builder
inv.Stdout = &stdout
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "Resource not found or you do not have access to this resource")
})
// Note: not testing with --follow as it is inherently racy.
t.Run("current build", func(t *testing.T) {
t.Parallel()
inv, root := clitest.New(t, "logs", wb1.Workspace.Name)
clitest.SetupConfig(t, memberClient, root)
ctx := testutil.Context(t, testutil.WaitShort)
var stdout strings.Builder
inv.Stdout = &stdout
err := inv.WithContext(ctx).Run()
require.NoError(t, err, "failed to fetch logs for current build")
assertLogOutput(t, wb1, stdout.String())
assertAntagonist(t, wb2, stdout.String())
})
t.Run("specific build", func(t *testing.T) {
t.Parallel()
inv, root := clitest.New(t, "logs", wb1.Workspace.Name, "-n", fmt.Sprintf("%d", wb1.Build.BuildNumber))
clitest.SetupConfig(t, memberClient, root)
ctx := testutil.Context(t, testutil.WaitShort)
var stdout strings.Builder
inv.Stdout = &stdout
err := inv.WithContext(ctx).Run()
require.NoError(t, err, "failed to fetch logs for specific build")
assertLogOutput(t, wb1, stdout.String())
assertAntagonist(t, wb2, stdout.String())
})
t.Run("build out of range", func(t *testing.T) {
t.Parallel()
inv, root := clitest.New(t, "logs", wb1.Workspace.Name, "-n", "-9999")
clitest.SetupConfig(t, memberClient, root)
ctx := testutil.Context(t, testutil.WaitShort)
var stdout strings.Builder
inv.Stdout = &stdout
err := inv.WithContext(ctx).Run()
require.ErrorContains(t, err, "invalid build number offset")
})
}
+2 -1
View File
@@ -5,8 +5,9 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) notifications() *serpent.Command {
+3 -9
View File
@@ -169,8 +169,8 @@ func (r *RootCmd) openVSCode() *serpent.Command {
// Note that this is irrelevant for devcontainer sub agents, as
// they always have a directory set.
if workspaceAgent.Directory != "" {
workspace, workspaceAgent, err = waitForAgentCond(ctx, client, workspace, workspaceAgent, func(wa codersdk.WorkspaceAgent) bool {
return wa.LifecycleState != codersdk.WorkspaceAgentLifecycleCreated
workspace, workspaceAgent, err = waitForAgentCond(ctx, client, workspace, workspaceAgent, func(_ codersdk.WorkspaceAgent) bool {
return workspaceAgent.LifecycleState != codersdk.WorkspaceAgentLifecycleCreated
})
if err != nil {
return xerrors.Errorf("wait for agent: %w", err)
@@ -183,13 +183,7 @@ func (r *RootCmd) openVSCode() *serpent.Command {
directory = inv.Args[1]
}
// If we're opening into a dev container, we should use the directory of the dev container.
workingDirectory := workspaceAgent.ExpandedDirectory
if workingDirectory == "" && devcontainer.Agent != nil {
workingDirectory = devcontainer.Agent.Directory
}
directory, err = resolveAgentAbsPath(workingDirectory, directory, workspaceAgent.OperatingSystem, insideThisWorkspace)
directory, err = resolveAgentAbsPath(workspaceAgent.ExpandedDirectory, directory, workspaceAgent.OperatingSystem, insideThisWorkspace)
if err != nil {
return xerrors.Errorf("resolve agent path: %w", err)
}
+9 -5
View File
@@ -10,21 +10,25 @@ import (
"strings"
"time"
"github.com/briandowns/spinner"
"golang.org/x/xerrors"
"tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/briandowns/spinner"
"github.com/coder/pretty"
"github.com/coder/serpent"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/cliutil"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/healthsdk"
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
)
type pingSummary struct {
+3 -2
View File
@@ -15,8 +15,9 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
+3 -2
View File
@@ -5,10 +5,11 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) publickey() *serpent.Command {
+3 -2
View File
@@ -5,10 +5,11 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
)
func (r *RootCmd) rename() *serpent.Command {
+6 -5
View File
@@ -7,15 +7,16 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/coderd/database/awsiamrds"
"github.com/coder/coder/v2/coderd/userpassword"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/userpassword"
)
func (*RootCmd) resetPassword() *serpent.Command {
+4 -20
View File
@@ -29,6 +29,10 @@ import (
"golang.org/x/mod/semver"
"golang.org/x/xerrors"
"github.com/coder/pretty"
"github.com/coder/serpent"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/config"
@@ -37,8 +41,6 @@ import (
"github.com/coder/coder/v2/cli/telemetry"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/pretty"
"github.com/coder/serpent"
)
var (
@@ -115,7 +117,6 @@ func (r *RootCmd) CoreSubcommands() []*serpent.Command {
r.deleteWorkspace(),
r.favorite(),
r.list(),
r.logs(),
r.open(),
r.ping(),
r.rename(),
@@ -684,7 +685,6 @@ func (r *RootCmd) HeaderTransport(ctx context.Context, serverURL *url.URL) (*cod
func (r *RootCmd) createHTTPClient(ctx context.Context, serverURL *url.URL, inv *serpent.Invocation) (*http.Client, error) {
transport := http.DefaultTransport
transport = wrapTransportWithTelemetryHeader(transport, inv)
transport = wrapTransportWithUserAgentHeader(transport, inv)
if !r.noVersionCheck {
transport = wrapTransportWithVersionMismatchCheck(transport, inv, buildinfo.Version(), func(ctx context.Context) (codersdk.BuildInfoResponse, error) {
// Create a new client without any wrapped transport
@@ -1498,22 +1498,6 @@ func wrapTransportWithTelemetryHeader(transport http.RoundTripper, inv *serpent.
})
}
// wrapTransportWithUserAgentHeader sets a User-Agent header for all CLI requests
// that includes the CLI version, os/arch, and the specific command being run.
func wrapTransportWithUserAgentHeader(transport http.RoundTripper, inv *serpent.Invocation) http.RoundTripper {
var (
userAgent string
once sync.Once
)
return roundTripper(func(req *http.Request) (*http.Response, error) {
once.Do(func() {
userAgent = fmt.Sprintf("coder-cli/%s (%s/%s; %s)", buildinfo.Version(), runtime.GOOS, runtime.GOARCH, inv.Command.FullName())
})
req.Header.Set("User-Agent", userAgent)
return transport.RoundTrip(req)
})
}
type roundTripper func(req *http.Request) (*http.Response, error)
func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
-56
View File
@@ -380,59 +380,3 @@ func agentClientCommand(clientRef **agentsdk.Client) *serpent.Command {
agentAuth.AttachOptions(cmd, false)
return cmd
}
func TestWrapTransportWithUserAgentHeader(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
cmdArgs []string
cmdEnv map[string]string
expectedUserAgentHeader string
}{
{
name: "top-level command",
cmdArgs: []string{"login"},
expectedUserAgentHeader: fmt.Sprintf("coder-cli/%s (%s/%s; coder login)", buildinfo.Version(), runtime.GOOS, runtime.GOARCH),
},
{
name: "nested commands",
cmdArgs: []string{"templates", "list"},
expectedUserAgentHeader: fmt.Sprintf("coder-cli/%s (%s/%s; coder templates list)", buildinfo.Version(), runtime.GOOS, runtime.GOARCH),
},
{
name: "does not include positional args, flags, or env",
cmdArgs: []string{"templates", "push", "my-template", "-d", "/path/to/template", "--yes", "--var", "myvar=myvalue"},
cmdEnv: map[string]string{"SECRET_KEY": "secret_value"},
expectedUserAgentHeader: fmt.Sprintf("coder-cli/%s (%s/%s; coder templates push)", buildinfo.Version(), runtime.GOOS, runtime.GOARCH),
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ch := make(chan string, 1)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
select {
case ch <- r.Header.Get("User-Agent"):
default: // already sent
}
}))
t.Cleanup(srv.Close)
args := append([]string{}, tc.cmdArgs...)
inv, _ := clitest.New(t, args...)
inv.Environ.Set("CODER_URL", srv.URL)
for k, v := range tc.cmdEnv {
inv.Environ.Set(k, v)
}
ctx := testutil.Context(t, testutil.WaitShort)
_ = inv.WithContext(ctx).Run() // Ignore error as we only care about headers.
actual := testutil.RequireReceive(ctx, t, ch)
require.Equal(t, tc.expectedUserAgentHeader, actual, "User-Agent should match expected format exactly")
})
}
}
+26 -58
View File
@@ -54,8 +54,15 @@ import (
"gopkg.in/yaml.v3"
"tailscale.com/tailcfg"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/coderd/pproflabel"
"github.com/coder/pretty"
"github.com/coder/quartz"
"github.com/coder/retry"
"github.com/coder/serpent"
"github.com/coder/wgtunnel/tunnelsdk"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/cli/clilog"
"github.com/coder/coder/v2/cli/cliui"
@@ -79,7 +86,6 @@ import (
"github.com/coder/coder/v2/coderd/notifications"
"github.com/coder/coder/v2/coderd/notifications/reports"
"github.com/coder/coder/v2/coderd/oauthpki"
"github.com/coder/coder/v2/coderd/pproflabel"
"github.com/coder/coder/v2/coderd/prometheusmetrics"
"github.com/coder/coder/v2/coderd/prometheusmetrics/insights"
"github.com/coder/coder/v2/coderd/promoauth"
@@ -105,11 +111,6 @@ import (
"github.com/coder/coder/v2/provisionersdk"
sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/tailnet"
"github.com/coder/pretty"
"github.com/coder/quartz"
"github.com/coder/retry"
"github.com/coder/serpent"
"github.com/coder/wgtunnel/tunnelsdk"
)
func createOIDCConfig(ctx context.Context, logger slog.Logger, vals *codersdk.DeploymentValues) (*coderd.OIDCConfig, error) {
@@ -747,16 +748,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
// "bare" read on this channel.
var pubsubWatchdogTimeout <-chan struct{}
maxOpenConns := int(vals.PostgresConnMaxOpen.Value())
maxIdleConns, err := codersdk.ComputeMaxIdleConns(maxOpenConns, vals.PostgresConnMaxIdle.Value())
if err != nil {
return xerrors.Errorf("compute max idle connections: %w", err)
}
logger.Debug(ctx, "creating database connection pool", slog.F("max_open_conns", maxOpenConns), slog.F("max_idle_conns", maxIdleConns))
sqlDB, dbURL, err := getAndMigratePostgresDB(ctx, logger, vals.PostgresURL.String(), codersdk.PostgresAuth(vals.PostgresAuth), sqlDriver,
WithMaxOpenConns(maxOpenConns),
WithMaxIdleConns(maxIdleConns),
)
sqlDB, dbURL, err := getAndMigratePostgresDB(ctx, logger, vals.PostgresURL.String(), codersdk.PostgresAuth(vals.PostgresAuth), sqlDriver)
if err != nil {
return xerrors.Errorf("connect to postgres: %w", err)
}
@@ -2333,29 +2325,6 @@ func IsLocalhost(host string) bool {
return host == "localhost" || host == "127.0.0.1" || host == "::1"
}
// PostgresConnectOptions contains options for connecting to Postgres.
type PostgresConnectOptions struct {
MaxOpenConns int
MaxIdleConns int
}
// PostgresConnectOption is a functional option for ConnectToPostgres.
type PostgresConnectOption func(*PostgresConnectOptions)
// WithMaxOpenConns sets the maximum number of open connections to the database.
func WithMaxOpenConns(n int) PostgresConnectOption {
return func(o *PostgresConnectOptions) {
o.MaxOpenConns = n
}
}
// WithMaxIdleConns sets the maximum number of idle connections in the pool.
func WithMaxIdleConns(n int) PostgresConnectOption {
return func(o *PostgresConnectOptions) {
o.MaxIdleConns = n
}
}
// ConnectToPostgres takes in the migration command to run on the database once
// it connects. To avoid running migrations, pass in `nil` or a no-op function.
// Regardless of the passed in migration function, if the database is not fully
@@ -2363,15 +2332,7 @@ func WithMaxIdleConns(n int) PostgresConnectOption {
// future or past migration version.
//
// If no error is returned, the database is fully migrated and up to date.
func ConnectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string, migrate func(db *sql.DB) error, opts ...PostgresConnectOption) (*sql.DB, error) {
// Apply defaults.
options := PostgresConnectOptions{
MaxOpenConns: 10,
MaxIdleConns: 3,
}
for _, opt := range opts {
opt(&options)
}
func ConnectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string, migrate func(db *sql.DB) error) (*sql.DB, error) {
logger.Debug(ctx, "connecting to postgresql")
var err error
@@ -2454,12 +2415,19 @@ func ConnectToPostgres(ctx context.Context, logger slog.Logger, driver string, d
// cannot accept new connections, so we try to limit that here.
// Requests will wait for a new connection instead of a hard error
// if a limit is set.
sqlDB.SetMaxOpenConns(options.MaxOpenConns)
// Limit idle connections to reduce connection churn while keeping some
// connections ready for reuse. When a connection is returned to the pool
// but the idle pool is full, it's closed immediately - which can cause
// connection establishment overhead when load fluctuates.
sqlDB.SetMaxIdleConns(options.MaxIdleConns)
sqlDB.SetMaxOpenConns(10)
// Allow a max of 3 idle connections at a time. Lower values end up
// creating a lot of connection churn. Since each connection uses about
// 10MB of memory, we're allocating 30MB to Postgres connections per
// replica, but is better than causing Postgres to spawn a thread 15-20
// times/sec. PGBouncer's transaction pooling is not the greatest so
// it's not optimal for us to deploy.
//
// This was set to 10 before we started doing HA deployments, but 3 was
// later determined to be a better middle ground as to not use up all
// of PGs default connection limit while simultaneously avoiding a lot
// of connection churn.
sqlDB.SetMaxIdleConns(3)
dbNeedsClosing = false
return sqlDB, nil
@@ -2863,7 +2831,7 @@ func signalNotifyContext(ctx context.Context, inv *serpent.Invocation, sig ...os
return inv.SignalNotifyContext(ctx, sig...)
}
func getAndMigratePostgresDB(ctx context.Context, logger slog.Logger, postgresURL string, auth codersdk.PostgresAuth, sqlDriver string, opts ...PostgresConnectOption) (*sql.DB, string, error) {
func getAndMigratePostgresDB(ctx context.Context, logger slog.Logger, postgresURL string, auth codersdk.PostgresAuth, sqlDriver string) (*sql.DB, string, error) {
dbURL, err := escapePostgresURLUserInfo(postgresURL)
if err != nil {
return nil, "", xerrors.Errorf("escaping postgres URL: %w", err)
@@ -2876,7 +2844,7 @@ func getAndMigratePostgresDB(ctx context.Context, logger slog.Logger, postgresUR
}
}
sqlDB, err := ConnectToPostgres(ctx, logger, sqlDriver, dbURL, migrations.Up, opts...)
sqlDB, err := ConnectToPostgres(ctx, logger, sqlDriver, dbURL, migrations.Up)
if err != nil {
return nil, "", xerrors.Errorf("connect to postgres: %w", err)
}
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"github.com/google/uuid"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/awsiamrds"
+2 -2
View File
@@ -11,8 +11,8 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
"github.com/coder/serpent"
+3 -2
View File
@@ -7,8 +7,9 @@ import (
"golang.org/x/xerrors"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/awsiamrds"
+1 -1
View File
@@ -41,7 +41,7 @@ import (
"tailscale.com/derp/derphttp"
"tailscale.com/types/key"
"cdr.dev/slog/v3/sloggers/slogtest"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/buildinfo"
"github.com/coder/coder/v2/cli"
"github.com/coder/coder/v2/cli/clitest"
+2 -1
View File
@@ -5,9 +5,10 @@ import (
"fmt"
"regexp"
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/google/uuid"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
+3 -3
View File
@@ -197,7 +197,7 @@ func TestSharingStatus(t *testing.T) {
ctx = testutil.Context(t, testutil.WaitMedium)
)
err := workspaceOwnerClient.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
err := client.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
UserRoles: map[string]codersdk.WorkspaceRole{
toShareWithUser.ID.String(): codersdk.WorkspaceRoleUse,
},
@@ -248,7 +248,7 @@ func TestSharingRemove(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
// Share the workspace with a user to later remove
err := workspaceOwnerClient.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
err := client.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
UserRoles: map[string]codersdk.WorkspaceRole{
toShareWithUser.ID.String(): codersdk.WorkspaceRoleUse,
toRemoveUser.ID.String(): codersdk.WorkspaceRoleUse,
@@ -309,7 +309,7 @@ func TestSharingRemove(t *testing.T) {
ctx := testutil.Context(t, testutil.WaitMedium)
// Share the workspace with a user to later remove
err := workspaceOwnerClient.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
err := client.UpdateWorkspaceACL(ctx, workspace.ID, codersdk.UpdateWorkspaceACL{
UserRoles: map[string]codersdk.WorkspaceRole{
toRemoveUser2.ID.String(): codersdk.WorkspaceRoleUse,
toRemoveUser1.ID.String(): codersdk.WorkspaceRoleUse,
+2 -1
View File
@@ -4,9 +4,10 @@ import (
"sort"
"sync"
"github.com/google/uuid"
"golang.org/x/xerrors"
"github.com/google/uuid"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
+2 -2
View File
@@ -10,8 +10,8 @@ import (
tsspeedtest "tailscale.com/net/speedtest"
"tailscale.com/wgengine/capture"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/serpent"
+2 -2
View File
@@ -32,8 +32,8 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"tailscale.com/types/netlogtype"
"cdr.dev/slog/v3"
"cdr.dev/slog/v3/sloggers/sloghuman"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/cliutil"

Some files were not shown because too many files have changed in this diff Show More