Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9aa5cf6df3 |
+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 ""
|
||||
|
||||
Reference in New Issue
Block a user