Move logging configuration to be per-domain (#399)

* chore: per-domain logging

* fix: lint

* fix: revert cdn configuration disabling the access log

* feat: more granular controls for logging

* chore(cr): bump copyright year to 2022

* fix(cr): missing error_log level in the global config

* fix(cr): `is-changed` indicators

* chore(cr): newline at end of file + eslint enforcement

* fix(cr): rows alignment when checkbox applies

* fix(cr): don't use default computed values

* fix: lint

* chore: use new flag names to allow backward compatability

* chore: global `access_log` should always be `off`

* feat: migrate old logging to new

* feat: option to turn on access_log and error_log on redirects

* fix: update copyright year

* fix: missing translation

* fix(cr): migration from global `error_log` being empty

* fix(cr): missing `return`

* fix(cr): account for a `server` dictionary without `domain`

* fix(cr): migrate previous `access_log` and `error_log` paths using the previous behavior

* chore(cr): additional logging comment

* feat(cr): disable error_log per domain

* fix(logging): use default paths

* fix(logging): retain the user values for error_log when toggling the log on/off

* fix(bc): new params shouldn't be overridden
This commit is contained in:
Kobi Meirson
2022-11-14 17:37:44 +02:00
committed by GitHub
parent f44832ed7a
commit e2a95a5ed4
31 changed files with 406 additions and 77 deletions

View File

@@ -227,6 +227,7 @@ THE SOFTWARE.
import ExternalLink from 'do-vue/src/templates/external_link';
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
import { serverDomainDefault } from '../../util/defaults';
import PrettyCheck from '../inputs/checkbox';
import PrettyRadio from '../inputs/radio';
@@ -269,7 +270,7 @@ THE SOFTWARE.
},
letsEncryptEmail: {
default: '',
computed: 'info@example.com', // No default value, but a default computed
computed: `info@${serverDomainDefault}`, // No default value, but a default computed
enabled: true,
},
sslCertificate: {

View File

@@ -26,35 +26,124 @@ THE SOFTWARE.
<template>
<div>
<div class="field is-horizontal">
<div class="field-label">
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">access_log {{ $t('templates.domainSections.logging.byDomain') }}</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${accessLogChanged ? ' is-changed' : ''}`">
<div :class="`control${accessLogEnabledChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="accessLog" class="p-default p-curve p-fill p-icon">
<PrettyCheck v-model="accessLogEnabled" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.logging.enableForThisDomain') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.accessLogEnabled.computed" :class="`control field is-horizontal is-expanded${accessLogPathChanged ? ' is-changed' : ''}`">
<input
v-model="accessLogPath"
class="input"
type="text"
:placeholder="$props.data.accessLogPath.default"
/>
</div>
</div>
</div>
</div>
<div v-if="$props.data.accessLogEnabled.computed" class="field is-horizontal">
<div class="field-label">
<label class="label">access_log {{ $t('templates.domainSections.logging.arguments') }}</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${accessLogParametersChanged ? ' is-changed' : ''}`">
<input
v-model="accessLogParameters"
class="input"
type="text"
:placeholder="$props.data.accessLogParameters.default"
/>
</div>
</div>
</div>
</div>
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">access_log {{ $t('templates.domainSections.logging.forRedirects') }}</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${redirectAccessLogChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="redirectAccessLog" class="p-default p-curve p-fill p-icon">
{{ $t('common.enable') }}
</PrettyCheck>
</div>
</div>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label">
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">error_log {{ $t('templates.domainSections.logging.byDomain') }}</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${errorLogChanged ? ' is-changed' : ''}`">
<div :class="`control${errorLogEnabledChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="errorLog" class="p-default p-curve p-fill p-icon">
<PrettyCheck v-model="errorLogEnabled" class="p-default p-curve p-fill p-icon">
{{ $t('templates.domainSections.logging.enableForThisDomain') }}
</PrettyCheck>
</div>
<div v-if="$props.data.errorLogEnabled.computed" :class="`control field is-horizontal is-expanded${errorLogPathChanged ? ' is-changed' : ''}`">
<input
v-model="errorLogPath"
class="input"
type="text"
:disabled="!errorLogPathEnabled"
:placeholder="$props.data.errorLogPath.default"
/>
</div>
</div>
</div>
</div>
</div>
<div v-if="$props.data.errorLogEnabled.computed" class="field is-horizontal">
<div class="field-label">
<label class="label">error_log {{ $t('templates.domainSections.logging.level') }}</label>
</div>
<div class="field-body">
<div class="field is-horizontal">
<div
v-for="value in $props.data.errorLogLevel.options"
:class="`control${errorLogLevelChanged && value === errorLogLevel ? ' is-changed' : ''}`"
>
<div class="radio">
<PrettyRadio v-model="errorLogLevel" :value="value" class="p-default p-round p-fill p-icon">
{{ value }}
</PrettyRadio>
</div>
</div>
</div>
</div>
</div>
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">error_log {{ $t('templates.domainSections.logging.forRedirects') }}</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${redirectErrorLogChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="redirectErrorLog" class="p-default p-curve p-fill p-icon">
{{ $t('common.enable') }}
</PrettyCheck>
</div>
</div>
</div>
</div>
@@ -65,14 +154,41 @@ THE SOFTWARE.
<script>
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
import { accessLogPathDefault, accessLogParamsDefault, errorLogPathDefault, errorLogPathDisabled, errorLogLevelDefault, errorLogLevelOptions, errorLogLevelDisabled } from '../../util/logging';
import PrettyCheck from '../inputs/checkbox';
import PrettyRadio from '../inputs/radio';
const defaults = {
accessLog: {
accessLogEnabled: {
default: true,
enabled: true,
},
accessLogPath: {
default: accessLogPathDefault,
enabled: true,
},
accessLogParameters: {
default: accessLogParamsDefault,
enabled: true,
},
redirectAccessLog: {
default: false,
enabled: true,
},
errorLog: {
errorLogEnabled: {
default: true,
enabled: true,
},
errorLogPath: {
default: errorLogPathDefault,
enabled: true,
},
errorLogLevel: {
default: errorLogLevelDefault,
options: [errorLogLevelDisabled, ...errorLogLevelOptions],
enabled: true,
},
redirectErrorLog: {
default: false,
enabled: true,
},
@@ -85,10 +201,26 @@ THE SOFTWARE.
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
},
computed: computedFromDefaults(defaults, 'logging'), // Getters & setters for the delegated data
watch: {
'$props.data.errorLogLevel': {
handler(data) {
// disable `error_log` path selection if log level is set to `none`
if (data.computed === errorLogLevelDisabled) {
this.$props.data.errorLogPath.enabled = false;
this.$props.data.errorLogPath.computed = errorLogPathDisabled;
} else if (!this.$props.data.errorLogPath.enabled) {
this.$props.data.errorLogPath.enabled = true;
this.$props.data.errorLogPath.computed = this.$props.data.errorLogPath.value;
}
},
deep: true,
},
},
};
</script>

View File

@@ -147,16 +147,17 @@ THE SOFTWARE.
<script>
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
import { serverDomainDefault } from '../../util/defaults';
import PrettyCheck from '../inputs/checkbox';
const defaults = {
domain: {
default: 'example.com',
default: serverDomainDefault,
enabled: true,
},
path: {
default: '',
computed: '/var/www/example.com', // No default value, but a default computed
computed: `/var/www/${serverDomainDefault}`, // No default value, but a default computed
enabled: true,
},
documentRoot: {

View File

@@ -26,37 +26,46 @@ THE SOFTWARE.
<template>
<div>
<div class="field is-horizontal">
<div class="field-label">
<label class="label">access_log</label>
<div class="field is-horizontal is-aligned-top">
<div class="field-label has-small-margin-top">
<label class="label">error_log</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${accessLogChanged ? ' is-changed' : ''}`">
<div :class="`control${errorLogEnabledChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="errorLogEnabled" class="p-default p-curve p-fill p-icon">
{{ $t('common.enable') }}
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.errorLogEnabled.computed" :class="`control field is-horizontal is-expanded${errorLogPathChanged ? ' is-changed' : ''}`">
<input
v-model="accessLog"
v-model="errorLogPath"
class="input"
type="text"
:placeholder="$props.data.accessLog.default"
:placeholder="$props.data.errorLogPath.default"
/>
</div>
</div>
</div>
</div>
<div class="field is-horizontal">
<div v-if="$props.data.errorLogEnabled.computed" class="field is-horizontal">
<div class="field-label">
<label class="label">error_log</label>
<label class="label">error_log {{ $t('templates.globalSections.logging.level') }}</label>
</div>
<div class="field-body">
<div class="field">
<div :class="`control${errorLogChanged ? ' is-changed' : ''}`">
<input
v-model="errorLog"
class="input"
type="text"
:placeholder="$props.data.errorLog.default"
/>
<div class="field is-horizontal">
<div
v-for="value in $props.data.errorLogLevel.options"
:class="`control${errorLogLevelChanged && value === errorLogLevel ? ' is-changed' : ''}`"
>
<div class="radio">
<PrettyRadio v-model="errorLogLevel" :value="value" class="p-default p-round p-fill p-icon">
{{ value }}
</PrettyRadio>
</div>
</div>
</div>
</div>
@@ -157,15 +166,22 @@ THE SOFTWARE.
<script>
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
import { errorLogPathDefault, errorLogLevelDefault, errorLogLevelOptions } from '../../util/logging';
import PrettyCheck from '../inputs/checkbox';
import PrettyRadio from '../inputs/radio';
const defaults = {
accessLog: {
default: '/var/log/nginx/access.log',
errorLogEnabled: {
default: false,
enabled: true,
},
errorLog: {
default: '/var/log/nginx/error.log warn',
errorLogPath: {
default: errorLogPathDefault,
enabled: true,
},
errorLogLevel: {
default: errorLogLevelDefault,
options: errorLogLevelOptions,
enabled: true,
},
logNotFound: {
@@ -217,6 +233,7 @@ THE SOFTWARE.
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent