Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9aa5cf6df3 | ||
|
|
ca39ff6e29 | ||
|
|
5d00b3c932 | ||
|
|
a380b5e8ae | ||
|
|
9ff5024a58 |
@@ -20,7 +20,7 @@ require (
|
||||
github.com/moby/term v0.5.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/schollz/progressbar/v3 v3.19.1
|
||||
golang.org/x/term v0.45.0
|
||||
golang.org/x/term v0.46.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gotest.tools/v3 v3.5.2
|
||||
)
|
||||
|
||||
@@ -1143,8 +1143,8 @@ golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||
golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE=
|
||||
golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
+50
-8
@@ -10,18 +10,60 @@ import (
|
||||
composetypes "github.com/docker/cli/cli/compose/types"
|
||||
)
|
||||
|
||||
// SetRecipeLabel adds the label 'coop-cloud.${STACK_NAME}.recipe=${RECIPE}' to the app container
|
||||
// to signal which recipe is connected to the deployed app
|
||||
func SetRecipeLabel(compose *composetypes.Config, stackName string, recipe string) {
|
||||
for _, service := range compose.Services {
|
||||
if service.Name == "app" {
|
||||
log.Debug(i18n.G("set recipe label 'coop-cloud.%s.recipe' to %s for %s", stackName, recipe, stackName))
|
||||
labelKey := fmt.Sprintf("coop-cloud.%s.recipe", stackName)
|
||||
service.Deploy.Labels[labelKey] = recipe
|
||||
// setLabel writes a label to both the service object and the task template of
|
||||
// every service of the stack.
|
||||
//
|
||||
// The task template labels end up on the containers themselves and are therefore
|
||||
// visible to container-level tooling (cAdvisor, log shippers, docker events),
|
||||
// which cannot read service labels at all.
|
||||
//
|
||||
// The service object is written as well because it is free: changing
|
||||
// Spec.Labels updates the service without recreating any task and because
|
||||
// `docker service ls --filter label=...` matches service labels only.
|
||||
func setLabel(compose *composetypes.Config, key string, value string) {
|
||||
for i := range compose.Services {
|
||||
if compose.Services[i].Deploy.Labels == nil {
|
||||
compose.Services[i].Deploy.Labels = composetypes.Labels{}
|
||||
}
|
||||
|
||||
if compose.Services[i].Labels == nil {
|
||||
compose.Services[i].Labels = composetypes.Labels{}
|
||||
}
|
||||
|
||||
compose.Services[i].Deploy.Labels[key] = value
|
||||
compose.Services[i].Labels[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// setAppLabel writes a label to the service object of the app service only.
|
||||
func setAppLabel(compose *composetypes.Config, key string, value string) {
|
||||
for i := range compose.Services {
|
||||
if compose.Services[i].Name != "app" {
|
||||
continue
|
||||
}
|
||||
|
||||
if compose.Services[i].Deploy.Labels == nil {
|
||||
compose.Services[i].Deploy.Labels = composetypes.Labels{}
|
||||
}
|
||||
|
||||
compose.Services[i].Deploy.Labels[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// SetRecipeLabel adds two distinct labels to signal which recipe is connected
|
||||
// to the deployed app:
|
||||
// - 'coop-cloud.${STACK_NAME}.recipe=${RECIPE}' on the app service object,
|
||||
// unchanged, as read back by GetLabel
|
||||
// - 'coop-cloud.recipe=${RECIPE}' on every service of the stack, so that
|
||||
// tooling can attribute any container to a recipe without knowing the
|
||||
// stack name up front
|
||||
func SetRecipeLabel(compose *composetypes.Config, stackName string, recipe string) {
|
||||
log.Debug(i18n.G("set recipe labels 'coop-cloud.%s.recipe' and 'coop-cloud.recipe' to %s for %s", stackName, recipe, stackName))
|
||||
|
||||
setAppLabel(compose, fmt.Sprintf("coop-cloud.%s.recipe", stackName), recipe)
|
||||
setLabel(compose, "coop-cloud.recipe", recipe)
|
||||
}
|
||||
|
||||
// SetChaosLabel adds the label 'coop-cloud.${STACK_NAME}.chaos=true/false' to the app container
|
||||
// to signal if the app is deployed in chaos mode
|
||||
func SetChaosLabel(compose *composetypes.Config, stackName string, chaos bool) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
testPkg "coopcloud.tech/abra/pkg/test"
|
||||
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||
|
||||
composetypes "github.com/docker/cli/cli/compose/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -61,3 +62,43 @@ func TestGetTimeoutFromLabel(t *testing.T) {
|
||||
assert.Equal(t, timeout, test.expectedTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetRecipeLabel(t *testing.T) {
|
||||
// the app service brings labels along on both levels, the db service
|
||||
// has none at all, so the pre-existing and the nil map case are covered
|
||||
compose := &composetypes.Config{
|
||||
Services: []composetypes.ServiceConfig{
|
||||
{
|
||||
Name: "app",
|
||||
Labels: composetypes.Labels{"example.container.label": "keep me"},
|
||||
Deploy: composetypes.DeployConfig{
|
||||
Labels: composetypes.Labels{"coop-cloud.backupbot.enabled": "true"},
|
||||
},
|
||||
},
|
||||
{Name: "db"},
|
||||
},
|
||||
}
|
||||
|
||||
appPkg.SetRecipeLabel(compose, "test_example_com", "test-recipe")
|
||||
|
||||
services := make(map[string]composetypes.ServiceConfig)
|
||||
for _, service := range compose.Services {
|
||||
services[service.Name] = service
|
||||
}
|
||||
|
||||
// the stack scoped label stays on the app service object only
|
||||
assert.Equal(t, "test-recipe",
|
||||
services["app"].Deploy.Labels["coop-cloud.test_example_com.recipe"])
|
||||
assert.NotContains(t, services["db"].Deploy.Labels,
|
||||
"coop-cloud.test_example_com.recipe")
|
||||
|
||||
// the static label reaches every container of the stack
|
||||
for name, service := range services {
|
||||
assert.Equal(t, "test-recipe", service.Labels["coop-cloud.recipe"], name)
|
||||
assert.Equal(t, "test-recipe", service.Deploy.Labels["coop-cloud.recipe"], name)
|
||||
}
|
||||
|
||||
// labels the recipe brought along are left alone
|
||||
assert.Equal(t, "keep me", services["app"].Labels["example.container.label"])
|
||||
assert.Equal(t, "true", services["app"].Deploy.Labels["coop-cloud.backupbot.enabled"])
|
||||
}
|
||||
|
||||
@@ -3047,7 +3047,7 @@ msgstr ""
|
||||
msgid "generated secrets %s shown again, please take note of them %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:63
|
||||
#: ./pkg/app/compose.go:105
|
||||
#, c-format
|
||||
msgid "get label '%s'"
|
||||
msgstr ""
|
||||
@@ -3695,7 +3695,7 @@ msgstr ""
|
||||
msgid "no %s exists, skipping reading gitignore paths"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:69
|
||||
#: ./pkg/app/compose.go:111
|
||||
#, c-format
|
||||
msgid "no %s label found for %s"
|
||||
msgstr ""
|
||||
@@ -4746,24 +4746,24 @@ msgstr ""
|
||||
msgid "set 'main' as the default branch"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:30
|
||||
#: ./pkg/app/compose.go:72
|
||||
#, c-format
|
||||
msgid "set label 'coop-cloud.%s.chaos' to %v for %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:41
|
||||
#: ./pkg/app/compose.go:83
|
||||
#, c-format
|
||||
msgid "set label 'coop-cloud.%s.chaos-version' to %v for %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:51
|
||||
#: ./pkg/app/compose.go:93
|
||||
#, c-format
|
||||
msgid "set label 'coop-cloud.%s.version' to %v for %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:18
|
||||
#: ./pkg/app/compose.go:61
|
||||
#, c-format
|
||||
msgid "set recipe label 'coop-cloud.%s.recipe' to %s for %s"
|
||||
msgid "set recipe labels 'coop-cloud.%s.recipe' and 'coop-cloud.recipe' to %s for %s"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/git/init.go:60
|
||||
@@ -5064,7 +5064,7 @@ msgstr ""
|
||||
msgid "timed out on undeploy (timeout=%v sec)"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:80
|
||||
#: ./pkg/app/compose.go:122
|
||||
#, c-format
|
||||
msgid "timeout label: %s"
|
||||
msgstr ""
|
||||
@@ -5172,7 +5172,7 @@ msgstr ""
|
||||
msgid "unable to continue, input required for initial version"
|
||||
msgstr ""
|
||||
|
||||
#: ./pkg/app/compose.go:85
|
||||
#: ./pkg/app/compose.go:127
|
||||
#, c-format
|
||||
msgid "unable to convert timeout label %s to int: %s"
|
||||
msgstr ""
|
||||
|
||||
@@ -3,7 +3,7 @@ version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: nginx:1.31.5
|
||||
image: nginx:1.31.6
|
||||
secrets:
|
||||
- test_pass_one
|
||||
- test_pass_two
|
||||
|
||||
@@ -3,7 +3,7 @@ version: "3.8"
|
||||
|
||||
services:
|
||||
app:
|
||||
image: nginx:1.31.5
|
||||
image: nginx:1.31.6
|
||||
networks:
|
||||
- proxy
|
||||
deploy:
|
||||
|
||||
+3
-3
@@ -3,16 +3,16 @@ kind: pipeline
|
||||
name: coopcloud.tech/tagcmp
|
||||
steps:
|
||||
- name: gofmt
|
||||
image: golang:1.26
|
||||
image: golang:1.27
|
||||
commands:
|
||||
- test -z "$(gofmt -l .)"
|
||||
|
||||
- name: go build
|
||||
image: golang:1.26
|
||||
image: golang:1.27
|
||||
commands:
|
||||
- go build -v .
|
||||
|
||||
- name: go test
|
||||
image: golang:1.26
|
||||
image: golang:1.27
|
||||
commands:
|
||||
- go test . -cover
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.25@sha256:31c1e53dfc1cc2d269deec9c83f58729fa3c53dc9a576f6426109d1e319e9e9a
|
||||
FROM golang:1.27@sha256:512690a5660563b57d37ecc31129e7f136e831db2aed24a1dbeb8ad7380dc0fa
|
||||
|
||||
ENV GOOS=linux
|
||||
ENV GOARCH=arm
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.25@sha256:31c1e53dfc1cc2d269deec9c83f58729fa3c53dc9a576f6426109d1e319e9e9a
|
||||
FROM golang:1.27@sha256:512690a5660563b57d37ecc31129e7f136e831db2aed24a1dbeb8ad7380dc0fa
|
||||
|
||||
ENV GOOS=linux
|
||||
ENV GOARCH=arm64
|
||||
|
||||
+17
-7
@@ -106,6 +106,9 @@ type Terminal struct {
|
||||
// a read. It aliases into inBuf.
|
||||
remainder []byte
|
||||
inBuf [256]byte
|
||||
// readErr is an error returned by a read that also returned data. It is
|
||||
// reported after all of that data has been processed.
|
||||
readErr error
|
||||
|
||||
// History records and retrieves lines of input read by [ReadLine] which
|
||||
// a user can retrieve and navigate using the up and down arrow keys.
|
||||
@@ -788,7 +791,11 @@ func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReadLine returns a line of input from the terminal.
|
||||
// ReadLine returns a line of input from the terminal, excluding the
|
||||
// trailing newline. It may return partial data along with an error.
|
||||
// An [io.EOF] error indicates the end of the stream. For other errors,
|
||||
// such as [ErrPasteIndicator] in bracketed paste mode, a subsequent
|
||||
// call may return more data.
|
||||
func (t *Terminal) ReadLine() (line string, err error) {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
@@ -863,21 +870,24 @@ func (t *Terminal) readLine() (line string, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if t.readErr != nil {
|
||||
err = t.readErr
|
||||
t.readErr = nil
|
||||
return
|
||||
}
|
||||
|
||||
// t.remainder is a slice at the beginning of t.inBuf
|
||||
// containing a partial key sequence
|
||||
readBuf := t.inBuf[len(t.remainder):]
|
||||
var n int
|
||||
|
||||
t.lock.Unlock()
|
||||
n, err = t.c.Read(readBuf)
|
||||
n, readErr := t.c.Read(readBuf)
|
||||
t.lock.Lock()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
t.remainder = t.inBuf[:n+len(t.remainder)]
|
||||
if readErr != nil {
|
||||
t.readErr = readErr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -704,8 +704,8 @@ golang.org/x/sys/plan9
|
||||
golang.org/x/sys/unix
|
||||
golang.org/x/sys/windows
|
||||
golang.org/x/sys/windows/registry
|
||||
# golang.org/x/term v0.45.0
|
||||
## explicit; go 1.25.0
|
||||
# golang.org/x/term v0.46.0
|
||||
## explicit; go 1.26.0
|
||||
golang.org/x/term
|
||||
# golang.org/x/text v0.39.0
|
||||
## explicit; go 1.25.0
|
||||
|
||||
Reference in New Issue
Block a user