logs: fix missing allocation logs after update to Nomad 1.5.4 (#17087)
When the server restarts for the upgrade, it loads the `structs.Job` from the Raft snapshot/logs. The jobspec has long since been parsed, so none of the guards around the default value are in play. The empty field value for `Enabled` is the zero value, which is false. This doesn't impact any running allocation because we don't replace running allocations when either the client or server restart. But as soon as any allocation gets rescheduled (ex. you drain all your clients during upgrades), it'll be using the `structs.Job` that the server has, which has `Enabled = false`, and logs will not be collected. This changeset fixes the bug by adding a new field `Disabled` which defaults to false (so that the zero value works), and deprecates the old field. Fixes #17076
This commit is contained in:
parent
b4c9f3bbc2
commit
17bd930ca9
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
logging: Fixed a bug where alloc logs would not be collected after an upgrade to 1.5.4
|
||||||
|
```
|
17
api/tasks.go
17
api/tasks.go
|
@ -639,16 +639,21 @@ func (g *TaskGroup) AddSpread(s *Spread) *TaskGroup {
|
||||||
|
|
||||||
// LogConfig provides configuration for log rotation
|
// LogConfig provides configuration for log rotation
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
MaxFiles *int `mapstructure:"max_files" hcl:"max_files,optional"`
|
MaxFiles *int `mapstructure:"max_files" hcl:"max_files,optional"`
|
||||||
MaxFileSizeMB *int `mapstructure:"max_file_size" hcl:"max_file_size,optional"`
|
MaxFileSizeMB *int `mapstructure:"max_file_size" hcl:"max_file_size,optional"`
|
||||||
Enabled *bool `mapstructure:"enabled" hcl:"enabled,optional"`
|
|
||||||
|
// COMPAT(1.6.0): Enabled had to be swapped for Disabled to fix a backwards
|
||||||
|
// compatibility bug when restoring pre-1.5.4 jobs. Remove in 1.6.0
|
||||||
|
Enabled *bool `mapstructure:"enabled" hcl:"enabled,optional"`
|
||||||
|
|
||||||
|
Disabled *bool `mapstructure:"disabled" hcl:"disabled,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultLogConfig() *LogConfig {
|
func DefaultLogConfig() *LogConfig {
|
||||||
return &LogConfig{
|
return &LogConfig{
|
||||||
MaxFiles: pointerOf(10),
|
MaxFiles: pointerOf(10),
|
||||||
MaxFileSizeMB: pointerOf(10),
|
MaxFileSizeMB: pointerOf(10),
|
||||||
Enabled: pointerOf(true),
|
Disabled: pointerOf(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,8 +664,8 @@ func (l *LogConfig) Canonicalize() {
|
||||||
if l.MaxFileSizeMB == nil {
|
if l.MaxFileSizeMB == nil {
|
||||||
l.MaxFileSizeMB = pointerOf(10)
|
l.MaxFileSizeMB = pointerOf(10)
|
||||||
}
|
}
|
||||||
if l.Enabled == nil {
|
if l.Disabled == nil {
|
||||||
l.Enabled = pointerOf(true)
|
l.Disabled = pointerOf(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ type logmonHook struct {
|
||||||
|
|
||||||
type logmonHookConfig struct {
|
type logmonHookConfig struct {
|
||||||
logDir string
|
logDir string
|
||||||
enabled bool
|
disabled bool
|
||||||
stdoutFifo string
|
stdoutFifo string
|
||||||
stderrFifo string
|
stderrFifo string
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,12 @@ func newLogMonHook(tr *TaskRunner, logger hclog.Logger) *logmonHook {
|
||||||
|
|
||||||
func newLogMonHookConfig(taskName string, logCfg *structs.LogConfig, logDir string) *logmonHookConfig {
|
func newLogMonHookConfig(taskName string, logCfg *structs.LogConfig, logDir string) *logmonHookConfig {
|
||||||
cfg := &logmonHookConfig{
|
cfg := &logmonHookConfig{
|
||||||
logDir: logDir,
|
logDir: logDir,
|
||||||
enabled: logCfg.Enabled,
|
disabled: logCfg.Disabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If logging is disabled configure task's stdout/err to point to devnull
|
// If logging is disabled configure task's stdout/err to point to devnull
|
||||||
if !logCfg.Enabled {
|
if logCfg.Disabled {
|
||||||
cfg.stdoutFifo = os.DevNull
|
cfg.stdoutFifo = os.DevNull
|
||||||
cfg.stderrFifo = os.DevNull
|
cfg.stderrFifo = os.DevNull
|
||||||
return cfg
|
return cfg
|
||||||
|
@ -116,7 +116,7 @@ func reattachConfigFromHookData(data map[string]string) (*plugin.ReattachConfig,
|
||||||
|
|
||||||
func (h *logmonHook) Prestart(ctx context.Context,
|
func (h *logmonHook) Prestart(ctx context.Context,
|
||||||
req *interfaces.TaskPrestartRequest, resp *interfaces.TaskPrestartResponse) error {
|
req *interfaces.TaskPrestartRequest, resp *interfaces.TaskPrestartResponse) error {
|
||||||
if !h.isLoggingEnabled() {
|
if h.isLoggingDisabled() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,10 +151,10 @@ func (h *logmonHook) Prestart(ctx context.Context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *logmonHook) isLoggingEnabled() bool {
|
func (h *logmonHook) isLoggingDisabled() bool {
|
||||||
if !h.config.enabled {
|
if h.config.disabled {
|
||||||
h.logger.Debug("log collection is disabled by task")
|
h.logger.Debug("log collection is disabled by task")
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal plugins have access to a capability to disable logging and
|
// internal plugins have access to a capability to disable logging and
|
||||||
|
@ -162,16 +162,16 @@ func (h *logmonHook) isLoggingEnabled() bool {
|
||||||
// currently only the docker driver exposes this to users.
|
// currently only the docker driver exposes this to users.
|
||||||
ic, ok := h.runner.driver.(drivers.InternalCapabilitiesDriver)
|
ic, ok := h.runner.driver.(drivers.InternalCapabilitiesDriver)
|
||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
caps := ic.InternalCapabilities()
|
caps := ic.InternalCapabilities()
|
||||||
if caps.DisableLogCollection {
|
if caps.DisableLogCollection {
|
||||||
h.logger.Debug("log collection is disabled by driver")
|
h.logger.Debug("log collection is disabled by driver")
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *logmonHook) prestartOneLoop(ctx context.Context, req *interfaces.TaskPrestartRequest) error {
|
func (h *logmonHook) prestartOneLoop(ctx context.Context, req *interfaces.TaskPrestartRequest) error {
|
||||||
|
@ -219,7 +219,7 @@ func (h *logmonHook) prestartOneLoop(ctx context.Context, req *interfaces.TaskPr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *logmonHook) Stop(_ context.Context, req *interfaces.TaskStopRequest, _ *interfaces.TaskStopResponse) error {
|
func (h *logmonHook) Stop(_ context.Context, req *interfaces.TaskStopRequest, _ *interfaces.TaskStopResponse) error {
|
||||||
if !h.isLoggingEnabled() {
|
if h.isLoggingDisabled() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ func TestTaskRunner_LogmonHook_Disabled(t *testing.T) {
|
||||||
|
|
||||||
alloc := mock.BatchAlloc()
|
alloc := mock.BatchAlloc()
|
||||||
task := alloc.Job.TaskGroups[0].Tasks[0]
|
task := alloc.Job.TaskGroups[0].Tasks[0]
|
||||||
task.LogConfig.Enabled = false
|
task.LogConfig.Disabled = true
|
||||||
|
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
|
||||||
|
|
|
@ -1242,11 +1242,7 @@ func ApiTaskToStructsTask(job *structs.Job, group *structs.TaskGroup,
|
||||||
|
|
||||||
structsTask.Resources = ApiResourcesToStructs(apiTask.Resources)
|
structsTask.Resources = ApiResourcesToStructs(apiTask.Resources)
|
||||||
|
|
||||||
structsTask.LogConfig = &structs.LogConfig{
|
structsTask.LogConfig = apiLogConfigToStructs(apiTask.LogConfig)
|
||||||
MaxFiles: *apiTask.LogConfig.MaxFiles,
|
|
||||||
MaxFileSizeMB: *apiTask.LogConfig.MaxFileSizeMB,
|
|
||||||
Enabled: *apiTask.LogConfig.Enabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(apiTask.Artifacts) > 0 {
|
if len(apiTask.Artifacts) > 0 {
|
||||||
structsTask.Artifacts = []*structs.TaskArtifact{}
|
structsTask.Artifacts = []*structs.TaskArtifact{}
|
||||||
|
@ -1809,13 +1805,21 @@ func apiLogConfigToStructs(in *api.LogConfig) *structs.LogConfig {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &structs.LogConfig{
|
return &structs.LogConfig{
|
||||||
Enabled: *in.Enabled,
|
Disabled: dereferenceBool(in.Disabled),
|
||||||
MaxFiles: dereferenceInt(in.MaxFiles),
|
MaxFiles: dereferenceInt(in.MaxFiles),
|
||||||
MaxFileSizeMB: dereferenceInt(in.MaxFileSizeMB),
|
MaxFileSizeMB: dereferenceInt(in.MaxFileSizeMB),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dereferenceBool(in *bool) bool {
|
||||||
|
if in == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *in
|
||||||
|
}
|
||||||
|
|
||||||
func dereferenceInt(in *int) int {
|
func dereferenceInt(in *int) int {
|
||||||
if in == nil {
|
if in == nil {
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -2767,7 +2767,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||||
KillTimeout: pointer.Of(10 * time.Second),
|
KillTimeout: pointer.Of(10 * time.Second),
|
||||||
KillSignal: "SIGQUIT",
|
KillSignal: "SIGQUIT",
|
||||||
LogConfig: &api.LogConfig{
|
LogConfig: &api.LogConfig{
|
||||||
Enabled: pointer.Of(true),
|
Disabled: pointer.Of(true),
|
||||||
MaxFiles: pointer.Of(10),
|
MaxFiles: pointer.Of(10),
|
||||||
MaxFileSizeMB: pointer.Of(100),
|
MaxFileSizeMB: pointer.Of(100),
|
||||||
},
|
},
|
||||||
|
@ -3185,7 +3185,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||||
KillTimeout: 10 * time.Second,
|
KillTimeout: 10 * time.Second,
|
||||||
KillSignal: "SIGQUIT",
|
KillSignal: "SIGQUIT",
|
||||||
LogConfig: &structs.LogConfig{
|
LogConfig: &structs.LogConfig{
|
||||||
Enabled: true,
|
Disabled: true,
|
||||||
MaxFiles: 10,
|
MaxFiles: 10,
|
||||||
MaxFileSizeMB: 100,
|
MaxFileSizeMB: 100,
|
||||||
},
|
},
|
||||||
|
@ -3342,7 +3342,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||||
KillTimeout: pointer.Of(10 * time.Second),
|
KillTimeout: pointer.Of(10 * time.Second),
|
||||||
KillSignal: "SIGQUIT",
|
KillSignal: "SIGQUIT",
|
||||||
LogConfig: &api.LogConfig{
|
LogConfig: &api.LogConfig{
|
||||||
Enabled: pointer.Of(true),
|
Disabled: pointer.Of(true),
|
||||||
MaxFiles: pointer.Of(10),
|
MaxFiles: pointer.Of(10),
|
||||||
MaxFileSizeMB: pointer.Of(100),
|
MaxFileSizeMB: pointer.Of(100),
|
||||||
},
|
},
|
||||||
|
@ -3468,7 +3468,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||||
KillTimeout: 10 * time.Second,
|
KillTimeout: 10 * time.Second,
|
||||||
KillSignal: "SIGQUIT",
|
KillSignal: "SIGQUIT",
|
||||||
LogConfig: &structs.LogConfig{
|
LogConfig: &structs.LogConfig{
|
||||||
Enabled: true,
|
Disabled: true,
|
||||||
MaxFiles: 10,
|
MaxFiles: 10,
|
||||||
MaxFileSizeMB: 100,
|
MaxFileSizeMB: 100,
|
||||||
},
|
},
|
||||||
|
@ -3639,16 +3639,39 @@ func TestConversion_dereferenceInt(t *testing.T) {
|
||||||
|
|
||||||
func TestConversion_apiLogConfigToStructs(t *testing.T) {
|
func TestConversion_apiLogConfigToStructs(t *testing.T) {
|
||||||
ci.Parallel(t)
|
ci.Parallel(t)
|
||||||
require.Nil(t, apiLogConfigToStructs(nil))
|
must.Nil(t, apiLogConfigToStructs(nil))
|
||||||
require.Equal(t, &structs.LogConfig{
|
must.Eq(t, &structs.LogConfig{
|
||||||
Enabled: true,
|
Disabled: true,
|
||||||
MaxFiles: 2,
|
MaxFiles: 2,
|
||||||
MaxFileSizeMB: 8,
|
MaxFileSizeMB: 8,
|
||||||
}, apiLogConfigToStructs(&api.LogConfig{
|
}, apiLogConfigToStructs(&api.LogConfig{
|
||||||
Enabled: pointer.Of(true),
|
Disabled: pointer.Of(true),
|
||||||
MaxFiles: pointer.Of(2),
|
MaxFiles: pointer.Of(2),
|
||||||
MaxFileSizeMB: pointer.Of(8),
|
MaxFileSizeMB: pointer.Of(8),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// COMPAT(1.6.0): verify backwards compatibility fixes
|
||||||
|
// Note: we're intentionally ignoring the Enabled: false case
|
||||||
|
must.Eq(t, &structs.LogConfig{Disabled: false},
|
||||||
|
apiLogConfigToStructs(&api.LogConfig{
|
||||||
|
Enabled: pointer.Of(false),
|
||||||
|
}))
|
||||||
|
must.Eq(t, &structs.LogConfig{Disabled: false},
|
||||||
|
apiLogConfigToStructs(&api.LogConfig{
|
||||||
|
Enabled: pointer.Of(true),
|
||||||
|
}))
|
||||||
|
must.Eq(t, &structs.LogConfig{Disabled: false},
|
||||||
|
apiLogConfigToStructs(&api.LogConfig{}))
|
||||||
|
must.Eq(t, &structs.LogConfig{Disabled: false},
|
||||||
|
apiLogConfigToStructs(&api.LogConfig{
|
||||||
|
Disabled: pointer.Of(false),
|
||||||
|
}))
|
||||||
|
must.Eq(t, &structs.LogConfig{Disabled: false},
|
||||||
|
apiLogConfigToStructs(&api.LogConfig{
|
||||||
|
Enabled: pointer.Of(false),
|
||||||
|
Disabled: pointer.Of(false),
|
||||||
|
}))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConversion_apiResourcesToStructs(t *testing.T) {
|
func TestConversion_apiResourcesToStructs(t *testing.T) {
|
||||||
|
@ -3743,7 +3766,7 @@ func TestConversion_apiConnectSidecarTaskToStructs(t *testing.T) {
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
KillTimeout: &timeout,
|
KillTimeout: &timeout,
|
||||||
LogConfig: &structs.LogConfig{
|
LogConfig: &structs.LogConfig{
|
||||||
Enabled: true,
|
Disabled: true,
|
||||||
MaxFiles: 2,
|
MaxFiles: 2,
|
||||||
MaxFileSizeMB: 8,
|
MaxFileSizeMB: 8,
|
||||||
},
|
},
|
||||||
|
@ -3762,7 +3785,7 @@ func TestConversion_apiConnectSidecarTaskToStructs(t *testing.T) {
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
KillTimeout: &timeout,
|
KillTimeout: &timeout,
|
||||||
LogConfig: &api.LogConfig{
|
LogConfig: &api.LogConfig{
|
||||||
Enabled: pointer.Of(true),
|
Disabled: pointer.Of(true),
|
||||||
MaxFiles: pointer.Of(2),
|
MaxFiles: pointer.Of(2),
|
||||||
MaxFileSizeMB: pointer.Of(8),
|
MaxFileSizeMB: pointer.Of(8),
|
||||||
},
|
},
|
||||||
|
|
|
@ -262,7 +262,8 @@ func parseTask(item *ast.ObjectItem, keys []string) (*api.Task, error) {
|
||||||
valid := []string{
|
valid := []string{
|
||||||
"max_files",
|
"max_files",
|
||||||
"max_file_size",
|
"max_file_size",
|
||||||
"enabled",
|
"enabled", // COMPAT(1.6.0): remove in favor of disabled
|
||||||
|
"disabled",
|
||||||
}
|
}
|
||||||
if err := checkHCLKeys(logsBlock.Val, valid); err != nil {
|
if err := checkHCLKeys(logsBlock.Val, valid); err != nil {
|
||||||
return nil, multierror.Prefix(err, "logs ->")
|
return nil, multierror.Prefix(err, "logs ->")
|
||||||
|
|
|
@ -350,7 +350,7 @@ func TestParse(t *testing.T) {
|
||||||
LogConfig: &api.LogConfig{
|
LogConfig: &api.LogConfig{
|
||||||
MaxFiles: intToPtr(14),
|
MaxFiles: intToPtr(14),
|
||||||
MaxFileSizeMB: intToPtr(101),
|
MaxFileSizeMB: intToPtr(101),
|
||||||
Enabled: boolToPtr(true),
|
Disabled: boolToPtr(false),
|
||||||
},
|
},
|
||||||
Artifacts: []*api.TaskArtifact{
|
Artifacts: []*api.TaskArtifact{
|
||||||
{
|
{
|
||||||
|
|
|
@ -194,7 +194,7 @@ job "binstore-storagelocker" {
|
||||||
}
|
}
|
||||||
|
|
||||||
logs {
|
logs {
|
||||||
enabled = true
|
disabled = false
|
||||||
max_files = 14
|
max_files = 14
|
||||||
max_file_size = 101
|
max_file_size = 101
|
||||||
}
|
}
|
||||||
|
|
|
@ -4420,7 +4420,7 @@ func TestTaskDiff(t *testing.T) {
|
||||||
LogConfig: &LogConfig{
|
LogConfig: &LogConfig{
|
||||||
MaxFiles: 1,
|
MaxFiles: 1,
|
||||||
MaxFileSizeMB: 10,
|
MaxFileSizeMB: 10,
|
||||||
Enabled: false,
|
Disabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Expected: &TaskDiff{
|
Expected: &TaskDiff{
|
||||||
|
@ -4432,9 +4432,9 @@ func TestTaskDiff(t *testing.T) {
|
||||||
Fields: []*FieldDiff{
|
Fields: []*FieldDiff{
|
||||||
{
|
{
|
||||||
Type: DiffTypeAdded,
|
Type: DiffTypeAdded,
|
||||||
Name: "Enabled",
|
Name: "Disabled",
|
||||||
Old: "",
|
Old: "",
|
||||||
New: "false",
|
New: "true",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DiffTypeAdded,
|
Type: DiffTypeAdded,
|
||||||
|
@ -4459,7 +4459,7 @@ func TestTaskDiff(t *testing.T) {
|
||||||
LogConfig: &LogConfig{
|
LogConfig: &LogConfig{
|
||||||
MaxFiles: 1,
|
MaxFiles: 1,
|
||||||
MaxFileSizeMB: 10,
|
MaxFileSizeMB: 10,
|
||||||
Enabled: false,
|
Disabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
New: &Task{},
|
New: &Task{},
|
||||||
|
@ -4472,8 +4472,8 @@ func TestTaskDiff(t *testing.T) {
|
||||||
Fields: []*FieldDiff{
|
Fields: []*FieldDiff{
|
||||||
{
|
{
|
||||||
Type: DiffTypeDeleted,
|
Type: DiffTypeDeleted,
|
||||||
Name: "Enabled",
|
Name: "Disabled",
|
||||||
Old: "false",
|
Old: "true",
|
||||||
New: "",
|
New: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -4499,14 +4499,14 @@ func TestTaskDiff(t *testing.T) {
|
||||||
LogConfig: &LogConfig{
|
LogConfig: &LogConfig{
|
||||||
MaxFiles: 1,
|
MaxFiles: 1,
|
||||||
MaxFileSizeMB: 10,
|
MaxFileSizeMB: 10,
|
||||||
Enabled: false,
|
Disabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
New: &Task{
|
New: &Task{
|
||||||
LogConfig: &LogConfig{
|
LogConfig: &LogConfig{
|
||||||
MaxFiles: 2,
|
MaxFiles: 2,
|
||||||
MaxFileSizeMB: 20,
|
MaxFileSizeMB: 20,
|
||||||
Enabled: true,
|
Disabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Expected: &TaskDiff{
|
Expected: &TaskDiff{
|
||||||
|
@ -4518,7 +4518,7 @@ func TestTaskDiff(t *testing.T) {
|
||||||
Fields: []*FieldDiff{
|
Fields: []*FieldDiff{
|
||||||
{
|
{
|
||||||
Type: DiffTypeEdited,
|
Type: DiffTypeEdited,
|
||||||
Name: "Enabled",
|
Name: "Disabled",
|
||||||
Old: "false",
|
Old: "false",
|
||||||
New: "true",
|
New: "true",
|
||||||
},
|
},
|
||||||
|
@ -4546,14 +4546,14 @@ func TestTaskDiff(t *testing.T) {
|
||||||
LogConfig: &LogConfig{
|
LogConfig: &LogConfig{
|
||||||
MaxFiles: 1,
|
MaxFiles: 1,
|
||||||
MaxFileSizeMB: 10,
|
MaxFileSizeMB: 10,
|
||||||
Enabled: false,
|
Disabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
New: &Task{
|
New: &Task{
|
||||||
LogConfig: &LogConfig{
|
LogConfig: &LogConfig{
|
||||||
MaxFiles: 1,
|
MaxFiles: 1,
|
||||||
MaxFileSizeMB: 20,
|
MaxFileSizeMB: 20,
|
||||||
Enabled: true,
|
Disabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Expected: &TaskDiff{
|
Expected: &TaskDiff{
|
||||||
|
@ -4565,7 +4565,7 @@ func TestTaskDiff(t *testing.T) {
|
||||||
Fields: []*FieldDiff{
|
Fields: []*FieldDiff{
|
||||||
{
|
{
|
||||||
Type: DiffTypeEdited,
|
Type: DiffTypeEdited,
|
||||||
Name: "Enabled",
|
Name: "Disabled",
|
||||||
Old: "false",
|
Old: "false",
|
||||||
New: "true",
|
New: "true",
|
||||||
},
|
},
|
||||||
|
|
|
@ -7225,7 +7225,7 @@ const (
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
MaxFiles int
|
MaxFiles int
|
||||||
MaxFileSizeMB int
|
MaxFileSizeMB int
|
||||||
Enabled bool
|
Disabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogConfig) Equal(o *LogConfig) bool {
|
func (l *LogConfig) Equal(o *LogConfig) bool {
|
||||||
|
@ -7241,7 +7241,7 @@ func (l *LogConfig) Equal(o *LogConfig) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.Enabled != o.Enabled {
|
if l.Disabled != o.Disabled {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7255,7 +7255,7 @@ func (l *LogConfig) Copy() *LogConfig {
|
||||||
return &LogConfig{
|
return &LogConfig{
|
||||||
MaxFiles: l.MaxFiles,
|
MaxFiles: l.MaxFiles,
|
||||||
MaxFileSizeMB: l.MaxFileSizeMB,
|
MaxFileSizeMB: l.MaxFileSizeMB,
|
||||||
Enabled: l.Enabled,
|
Disabled: l.Disabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7264,13 +7264,13 @@ func DefaultLogConfig() *LogConfig {
|
||||||
return &LogConfig{
|
return &LogConfig{
|
||||||
MaxFiles: 10,
|
MaxFiles: 10,
|
||||||
MaxFileSizeMB: 10,
|
MaxFileSizeMB: 10,
|
||||||
Enabled: true,
|
Disabled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate returns an error if the log config specified are less than the
|
// Validate returns an error if the log config specified are less than the
|
||||||
// minimum allowed. Note that because we have a non-zero default MaxFiles and
|
// minimum allowed. Note that because we have a non-zero default MaxFiles and
|
||||||
// MaxFileSizeMB, we can't validate that they're unset if Enabled=false
|
// MaxFileSizeMB, we can't validate that they're unset if Disabled=true
|
||||||
func (l *LogConfig) Validate() error {
|
func (l *LogConfig) Validate() error {
|
||||||
var mErr multierror.Error
|
var mErr multierror.Error
|
||||||
if l.MaxFiles < 1 {
|
if l.MaxFiles < 1 {
|
||||||
|
|
|
@ -194,7 +194,7 @@ FieldsLoop:
|
||||||
for _, fDiff := range oDiff.Fields {
|
for _, fDiff := range oDiff.Fields {
|
||||||
switch fDiff.Name {
|
switch fDiff.Name {
|
||||||
// force a destructive update if logger was enabled or disabled
|
// force a destructive update if logger was enabled or disabled
|
||||||
case "Enabled":
|
case "Disabled":
|
||||||
destructive = true
|
destructive = true
|
||||||
break ObjectsLoop
|
break ObjectsLoop
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,7 @@ func TestAnnotateTask(t *testing.T) {
|
||||||
Fields: []*structs.FieldDiff{
|
Fields: []*structs.FieldDiff{
|
||||||
{
|
{
|
||||||
Type: structs.DiffTypeAdded,
|
Type: structs.DiffTypeAdded,
|
||||||
Name: "Enabled",
|
Name: "Disabled",
|
||||||
Old: "true",
|
Old: "true",
|
||||||
New: "false",
|
New: "false",
|
||||||
},
|
},
|
||||||
|
|
|
@ -305,11 +305,11 @@ func tasksUpdated(jobA, jobB *structs.Job, taskGroup string) comparison {
|
||||||
return difference("task identity", at.Identity, bt.Identity)
|
return difference("task identity", at.Identity, bt.Identity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most LogConfig updates are in-place but if we change Enabled we need
|
// Most LogConfig updates are in-place but if we change Disabled we need
|
||||||
// to recreate the task to stop/start log collection and change the
|
// to recreate the task to stop/start log collection and change the
|
||||||
// stdout/stderr of the task
|
// stdout/stderr of the task
|
||||||
if at.LogConfig.Enabled != bt.LogConfig.Enabled {
|
if at.LogConfig.Disabled != bt.LogConfig.Disabled {
|
||||||
return difference("task log enabled", at.LogConfig.Enabled, bt.LogConfig.Enabled)
|
return difference("task log disabled", at.LogConfig.Disabled, bt.LogConfig.Disabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -604,7 +604,7 @@ fields:
|
||||||
## Stream Logs
|
## Stream Logs
|
||||||
|
|
||||||
This endpoint streams a task's stderr/stdout logs. Note that if logging is set
|
This endpoint streams a task's stderr/stdout logs. Note that if logging is set
|
||||||
to [enabled=false][] for the task, this endpoint will return a 404 error.
|
to [disabled=true][] for the task, this endpoint will return a 404 error.
|
||||||
|
|
||||||
| Method | Path | Produces |
|
| Method | Path | Produces |
|
||||||
| ------ | ------------------------------ | ------------ |
|
| ------ | ------------------------------ | ------------ |
|
||||||
|
@ -833,4 +833,4 @@ $ nomad operator api /v1/client/gc
|
||||||
```
|
```
|
||||||
|
|
||||||
[api-node-read]: /nomad/api-docs/nodes
|
[api-node-read]: /nomad/api-docs/nodes
|
||||||
[enabled=false]: /nomad/docs/job-specification/logs#enabled
|
[disabled=true]: /nomad/docs/job-specification/logs#disabled
|
||||||
|
|
|
@ -491,7 +491,7 @@ $ curl \
|
||||||
},
|
},
|
||||||
"KillTimeout": 5000000000,
|
"KillTimeout": 5000000000,
|
||||||
"LogConfig": {
|
"LogConfig": {
|
||||||
"Enabled": true,
|
"Disabled": false,
|
||||||
"MaxFiles": 10,
|
"MaxFiles": 10,
|
||||||
"MaxFileSizeMB": 10
|
"MaxFileSizeMB": 10
|
||||||
},
|
},
|
||||||
|
@ -763,7 +763,7 @@ $ curl \
|
||||||
"Leader": false,
|
"Leader": false,
|
||||||
"Lifecycle": null,
|
"Lifecycle": null,
|
||||||
"LogConfig": {
|
"LogConfig": {
|
||||||
"Enabled": true,
|
"Disabled": false,
|
||||||
"MaxFileSizeMB": 10,
|
"MaxFileSizeMB": 10,
|
||||||
"MaxFiles": 10
|
"MaxFiles": 10
|
||||||
},
|
},
|
||||||
|
@ -981,7 +981,7 @@ $ curl \
|
||||||
"Leader": false,
|
"Leader": false,
|
||||||
"Lifecycle": null,
|
"Lifecycle": null,
|
||||||
"LogConfig": {
|
"LogConfig": {
|
||||||
"Enabled": true,
|
"Disabled": false,
|
||||||
"MaxFileSizeMB": 10,
|
"MaxFileSizeMB": 10,
|
||||||
"MaxFiles": 10
|
"MaxFiles": 10
|
||||||
},
|
},
|
||||||
|
@ -1148,7 +1148,7 @@ $ curl \
|
||||||
"Leader": false,
|
"Leader": false,
|
||||||
"Lifecycle": null,
|
"Lifecycle": null,
|
||||||
"LogConfig": {
|
"LogConfig": {
|
||||||
"Enabled": true,
|
"Disabled": false,
|
||||||
"MaxFileSizeMB": 10,
|
"MaxFileSizeMB": 10,
|
||||||
"MaxFiles": 10
|
"MaxFiles": 10
|
||||||
},
|
},
|
||||||
|
|
|
@ -927,7 +927,7 @@ The `Affinity` object supports the following keys:
|
||||||
The `LogConfig` object configures the log rotation policy for a task's `stdout` and
|
The `LogConfig` object configures the log rotation policy for a task's `stdout` and
|
||||||
`stderr`. The `LogConfig` object supports the following attributes:
|
`stderr`. The `LogConfig` object supports the following attributes:
|
||||||
|
|
||||||
- `Enabled` - Enables log collection.
|
- `Disabled` - Disables log collection.
|
||||||
|
|
||||||
- `MaxFiles` - The maximum number of rotated files Nomad will retain for
|
- `MaxFiles` - The maximum number of rotated files Nomad will retain for
|
||||||
`stdout` and `stderr`, each tracked individually.
|
`stdout` and `stderr`, each tracked individually.
|
||||||
|
@ -942,7 +942,7 @@ a validation error when a job is submitted.
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"LogConfig": {
|
"LogConfig": {
|
||||||
"Enabled": true,
|
"Disabled": false,
|
||||||
"MaxFiles": 3,
|
"MaxFiles": 3,
|
||||||
"MaxFileSizeMB": 10
|
"MaxFileSizeMB": 10
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ job "docs" {
|
||||||
logs {
|
logs {
|
||||||
max_files = 10
|
max_files = 10
|
||||||
max_file_size = 10
|
max_file_size = 10
|
||||||
enabled = true
|
disabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,8 @@ please see the [`nomad alloc logs`][logs-command] command.
|
||||||
the total amount of disk space needed to retain the rotated set of files,
|
the total amount of disk space needed to retain the rotated set of files,
|
||||||
Nomad will return a validation error when a job is submitted.
|
Nomad will return a validation error when a job is submitted.
|
||||||
|
|
||||||
- `enabled` `(bool: true)` - Specifies that log collection should be enabled for
|
- `disabled` `(bool: false)` - Specifies that log collection should be enabled for
|
||||||
this task. If set to `false`, the task driver will attach stdout/stderr of the
|
this task. If set to `true`, the task driver will attach stdout/stderr of the
|
||||||
task to `/dev/null` (or `NUL` on Windows). You should only disable log
|
task to `/dev/null` (or `NUL` on Windows). You should only disable log
|
||||||
collection if your application has some other way of emitting logs, such as
|
collection if your application has some other way of emitting logs, such as
|
||||||
writing to a remote syslog server. Note that the `nomad alloc logs` command
|
writing to a remote syslog server. Note that the `nomad alloc logs` command
|
||||||
|
@ -61,7 +61,7 @@ please see the [`nomad alloc logs`][logs-command] command.
|
||||||
|
|
||||||
Some task drivers such as `docker` support a [`disable_log_collection`][]
|
Some task drivers such as `docker` support a [`disable_log_collection`][]
|
||||||
option. If the task driver's `disable_log_collection` option is set to `true`,
|
option. If the task driver's `disable_log_collection` option is set to `true`,
|
||||||
it will override `enabled=true` in the task's `logs` block.
|
it will override `disabled=false` in the task's `logs` block.
|
||||||
|
|
||||||
## `logs` Examples
|
## `logs` Examples
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue