diff --git a/.github/workflows/markdowner.py b/.github/workflows/markdowner.py index 24c7e6c20..3d274e14f 100644 --- a/.github/workflows/markdowner.py +++ b/.github/workflows/markdowner.py @@ -3,18 +3,23 @@ # find . -name '*.markdown' -type f -exec python3 .github/workflows/markdowner.py {} all \; | tee output.log import sys +import re from collections import defaultdict + class EasyDict(defaultdict): def __getattr__(self, key): return self[key] + def __setattr__(self, key, value): self[key] = value return value + def set_flag_list(self, l): for x in l: self.__setattr__(x, True) + def replace_with_dict(content, replacements, filename): for k, v in replacements.items(): while k in content: @@ -22,23 +27,58 @@ def replace_with_dict(content, replacements, filename): content = content.replace(k, v) return content + +def replace_with_regex_dict(content, replacements, filename): + for str_pattern, replacement in replacements.items(): + pattern = re.compile(str_pattern, flags=re.MULTILINE) + while True: + match = pattern.search(content) + if not match: + break + start, end = match.span() + match = match.group(0) + print(f"{filename}: {repr(match)} -> {repr(replacement)}") + content = content[0:start] + replacement + content[end:] + return content + + def process_codeblock(lines, filename, lineno_start): result = [] begin = lines[0] end = lines[-1] - lines = lines[1:-1] + lines = lines[1:-1] # Lines inside code block - prefix = begin[0:begin.index("```")] - lang = begin[len(prefix)+3:].strip() + prefix = begin[0 : begin.index("```")] + lang = begin[len(prefix) + 3 :].strip() + + # If the first line is a `[file=` label line, re-indent it to the same + # level as the code block: + file_line = None + if lines[0].strip().startswith("[file="): + file_line = lines[0] + should_be = prefix + file_line.strip() + if file_line != should_be: + lines[0] = should_be + file_line = should_be + print( + f"{filename}:{lineno_start}: Re-indented file line inside code block: {file_line.strip()}" + ) # Checks for warnings which make us leave the code block alone: + if not end == (prefix + "```"): lineno = lineno_start + len(lines) + 1 print(f"WARNING {filename}:{lineno}: End backticks not matching beginning") return [begin, *lines, end] lineno = lineno_start - for line in lines: + for i, line in enumerate(lines): + # If the first line is a [file=] label line, skip it, + # we've already indented it correctly above: + if i == 0 and file_line: + lineno += 1 + continue + # Empty lines are already correct, skip them: if line == "": lineno += 1 continue @@ -54,11 +94,19 @@ def process_codeblock(lines, filename, lineno_start): # Find the common indentation which we would like to remove: common_indent = None lineno = lineno_start - for line in lines: + for i, line in enumerate(lines): + # Don't consider [file= label line for common indent, + # we indented it to same level as opening backticks above: + if i == 0 and file_line: + lineno += 1 + continue + # Don't consider empty lines for common indentation: if line == "": lineno += 1 continue - if (line[len(prefix):][0] != ' '): + if line[len(prefix) :][0] != " ": + # Found content without extra indentation - + # no common indentation to remove. common_indent = None break index = len(prefix) @@ -78,16 +126,27 @@ def process_codeblock(lines, filename, lineno_start): # Remove common indent if found: if common_indent is not None and common_indent > 0: spaces = common_indent - lines = [x if x == "" else x[0:len(prefix)] + x[len(prefix) + spaces:] for x in lines] - print(f"{filename}:{lineno_start}: De-indented {lang + ' ' if lang else ''}code block") + if file_line: + lines = lines[1:] + lines = ([file_line] if file_line else []) + [ + x if x == "" else x[0 : len(prefix)] + x[len(prefix) + spaces :] + for x in lines + ] + print( + f"{filename}:{lineno_start}: De-indented {lang + ' ' if lang else ''}code block" + ) # Remove empty lines at beginning and end: while lines and lines[0] == "": lines = lines[1:] - print(f"{filename}:{lineno_start}: Removed empty line at beginning of {lang + ' ' if lang else ''} code block") + print( + f"{filename}:{lineno_start}: Removed empty line at beginning of {lang + ' ' if lang else ''} code block" + ) while lines and lines[-1] == "": lines = lines[0:-1] - print(f"{filename}:{lineno_start}: Removed empty line at beginning of {lang + ' ' if lang else ''} code block") + print( + f"{filename}:{lineno_start}: Removed empty line at beginning of {lang + ' ' if lang else ''} code block" + ) # "Render" result - May or may not be different result.append(begin) @@ -95,6 +154,7 @@ def process_codeblock(lines, filename, lineno_start): result.append(end) return result + def edit_codeblocks(content, filename): done = [] to_do = [] @@ -115,7 +175,9 @@ def edit_codeblocks(content, filename): lineno_start = lineno will_try = True elif count % 2 != 0: - print(f"WARNING {filename}:{lineno}: Start of code block not on start of line") + print( + f"WARNING {filename}:{lineno}: Start of code block not on start of line" + ) done.append(line) will_try = False state = "inside" @@ -133,7 +195,9 @@ def edit_codeblocks(content, filename): to_do = [] state = "outside" elif "```" in line: - print(f"WARNING {filename}:{lineno}: End of code block not on start of line") + print( + f"WARNING {filename}:{lineno}: End of code block not on start of line" + ) will_try = False done.extend(to_do) to_do = [] @@ -146,13 +210,14 @@ def edit_codeblocks(content, filename): content = "\n".join(done) return content + def perform_edits(content, flags, filename): if flags.trailing or flags.all: replacements = {" \n": "\n", "\t\n": "\n"} content = replace_with_dict(content, replacements, filename) if flags.ascii or flags.all: - replacements = {"‘":"'", "’": "'", "“": '"', "”": '"', "–": "-"} + replacements = {"‘": "'", "’": "'", "“": '"', "”": '"', "–": "-"} content = replace_with_dict(content, replacements, filename) if flags.eof or flags.all: @@ -164,9 +229,18 @@ def perform_edits(content, flags, filename): print(f"{filename}: Added newline before EOF") if flags.codeblocks or flags.all: + content = replace_with_regex_dict(content, replacements, filename) + replacements = { + # Empty line (double newline) before command: + r"(? git command something` are to be done on the command line (e.g. Command Prompt/PowerShell on Windows, bash etc. on Linux / Mac). Do not type the `>` at the start of the statement -- beging typing the instructions that follow it (e.g. `git...`). diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..551dad4e1 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,148 @@ +pipeline { + agent { label 'CONTAINERS' } + environment { + REPOS = "core enterprise nova masterfiles northerntechhq/nt-docs" + PR_BASE = getPR_BASE() + DOCS_BRANCH = getDOCS_BRANCH() + PACKAGE_JOB = "cf-remote" + PACKAGE_UPLOAD_DIRECTORY = "n/a" + PACKAGE_BUILD = "n/a" + } + parameters { + string(name: "CORE_REV", defaultValue: '', description: 'used for changelog, examples. Use NUMBER or "pull/NUMBER/merge" for pull request (it\'s merged version, THIS DOESN\'T MERGE THE PR) or "pull/NUMBER/head" to build the docs with the non-merged code. Special syntax \'tag:SOME_TAG\' can be used to use a tag as a revision.') + string(name: "NOVA_REV", defaultValue: '', description: 'used for changelog. Use NUMBER or "pull/NUMBER/merge" for pull request (it\'s merged version, THIS DOESN\'T MERGE THE PR) or "pull/NUMBER/head" to build the docs with the non-merged code. Special syntax \'tag:SOME_TAG\' can be used to use a tag as a revision.') + string(name: "ENTERPRISE_REV", defaultValue: '', description: 'used for changelog. Use NUMBER or "pull/NUMBER/merge" for pull request (it\'s merged version, THIS DOESN\'T MERGE THE PR) or "pull/NUMBER/head" to build the docs with the non-merged code. Special syntax \'tag:SOME_TAG\' can be used to use a tag as a revision.') + string(name: "MASTERFILES_REV", defaultValue: '', description: 'used to document masterfiles. Use NUMBER or "pull/NUMBER/merge" for pull request (it\'s merged version, THIS DOESN\'T MERGE THE PR) or "pull/NUMBER/head" to build the docs with the non-merged code. Special syntax \'tag:SOME_TAG\' can be used to use a tag as a revision.') + string(name: "DOCS_REV", defaultValue: '', description: 'Use NUMBER or "pull/NUMBER/merge" for pull request (it\'s merged version, THIS DOESN\'T MERGE THE PR) or "pull/NUMBER/head" to build the docs with the non-merged code. Special syntax \'tag:SOME_TAG\' can be used to use a tag as a revision.') + string(name: "NT_DOCS_REV", defaultValue: '', description: 'Use NUMBER or "pull/NUMBER/merge" for pull request (it\'s merged version, THIS DOESN\'T MERGE THE PR) or "pull/NUMBER/head" to build the docs with the non-merged code. Special syntax \'tag:SOME_TAG\' can be used to use a tag as a revision.') + string(name: "DOCS_BRANCH", defaultValue: '', description: 'Where to upload artifacts - to http://buildcache.cloud.cfengine.com/packages/build-documentation-$DOCS_BRANCH/ and https://docs.cfengine.com/docs/$DOCS_BRANCH/') + string(name: "PACKAGE_JOB", defaultValue: 'cf-remote', description: 'where to get CFEngine HUB package from, either a dir at http://buildcache.cloud.cfengine.com/packages like testing-pr or a keyword cf-remote to use cf-remote download') + string(name: "USE_NIGHTLIES_FOR", defaultValue: '', description: 'branch whose nightlies to use (master, 3.18.x, etc) - will be one of http://buildcache.cloud.cfengine.com/packages/testing-pr/jenkins-$USE_NIGHTLIES_FOR-nightly-pipeline-$NUMBER/') + } + options { + checkoutToSubdirectory('documentation') + } + stages { + stage('Environment check') { + steps { + sh 'env' + sh 'whoami; pwd; ls' + sh 'uname -a; cat /etc/os-release' + } + } + // we clean FIRST and NOT at the end of the job so that we can replay various stages and have the build result from previous runs + stage('Clean workspace') { + steps { + sh 'for r in $REPOS; do rm -rf "$(basename "$r")"; done' + } + } + stage('Checkout repositories'){ + steps { + script { + if (env.CHANGE_ID) { + sh "echo \"${pullRequest.title}\" > pull-request-title" + sh "echo \"${pullRequest.body}\" > pull-request-body" + } + } + sh "curl -O https://raw.githubusercontent.com/cfengine/buildscripts/refs/heads/master/ci/create-revisions-file.sh" + sh "chmod u+x ./create-revisions-file.sh" + sh "./create-revisions-file.sh" + sh "cat revisions" + sh "curl -O https://gitlab.com/Northern.tech/OpenSource/GODS/-/raw/master/parallel_git_rev_fetch.sh" + sh "chmod u+x ./parallel_git_rev_fetch.sh" + + withCredentials([sshUserPrivateKey(credentialsId:"autobuild", keyFileVariable: "key")]) { + sh 'export GIT_SSH_COMMAND="ssh -i $key"; ./parallel_git_rev_fetch.sh revisions' + } + } + } + stage('Build documentation') { + steps { + sh 'bash -x documentation/generator/build/run.sh' + } + } + stage('Publish to buildcache') { + steps { + sshPublisher( + // we must use alwaysPublishFromMaster: true because our CONTAINERS build hosts are not in the private network which has access to buildcache.cloud.cfengine.com + alwaysPublishFromMaster: true, + publishers: [ + sshPublisherDesc( + configName: 'buildcache.cloud.cfengine.com', + transfers: [ + sshTransfer( + cleanRemote: false, + excludes: '', + execCommand: ''' +#!/usr/bin/env bash +set -x +WRKDIR="$(pwd)" +export WRKDIR + +mkdir -p upload +mkdir -p output + +# find two tarballs +archive="$(find upload -name "cfengine-documentation-*.tar.gz")" +tarball=$(findfind upload -name packed-for-shipping.tar.gz) +echo "TARBALL: $tarball" +echo "ARCHIVE: $archive" + +# unpack $tarball +( # shubshell to change directories + cd "$(dirname "$tarball")" || exit + tar zxvf packed-for-shipping.tar.gz + rm packed-for-shipping.tar.gz + + # move $archive to the _site + mv "$WRKDIR/$archive" _site + + ls -la +) + +ls -la upload + +# note: this triggers systemd job to AV-scan new files +# and move them to proper places +mv upload/* output +''', + execTimeout: 120000, + flatten: false, + makeEmptyDirs: false, + noDefaultExcludes: false, + patternSeparator: '[, ]+', + remoteDirectory: getRemoteDirectory(), + remoteDirectorySDF: false, + removePrefix: '', + sourceFiles: 'output/' + ) // sshTransfer + ], // transfers + usePromotionTimestamp: false, + useWorkspaceInPromotion: false, + verbose: false + ) // sshPublisherDesc + ] // publishers + ) // sshPublisher + } // steps + } // stage('Publish to buildcache') + } // stages +} +def getDOCS_BRANCH() { + if (env.DOCS_BRANCH) { + return env.DOCS_BRANCH + } else if (env.CHANGE_ID) { + return "${env.CHANGE_TARGET}" + } else { + return "${env.BRANCH_NAME}" + } +} +def getPR_BASE() { + if (env.CHANGE_ID) { + return "${pullRequest.base}" + } else { + return "" + } +} +def getRemoteDirectory() { + return "upload/${env.BUILD_TAG}/build-documentation-${env.DOCS_BRANCH}/${env.BUILD_TAG}/" +} diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..67a27b506 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +.PHONY: check +check: + shellcheck generator/build/*.sh diff --git a/README.md b/README.md index c755d6e0d..ba071681b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# CFEngine Documentation +# CFEngine documentation This repository holds the sources for the technical [CFEngine documentation](https://docs.cfengine.com/docs/) in @@ -15,7 +15,7 @@ category when you create bugs. And of course you can search the bug tracker for known issues with the documentation, and help the community of CFEngine users by correcting some of them. -## Writing Documentation +## Writing documentation The CFEngine documentation is written in regular [markdown](https://daringfireball.net/projects/markdown/syntax), with some @@ -35,7 +35,40 @@ It is in general advisable to make small commits that are submitted through pull requests frequently. Otherwise any structural changes to documentation content can cause merge conflicts that are hard to resolve. -## Documentation Structure +### Capitalization + +Avoid capitalizing things unnecessarily (features, concepts, titles). +Titles and headings use sentence case (so don't capitalize each word). +Some names should always be capitalized in a specific way: + +* CFEngine +* CFEngine Build +* CFEngine Docs +* CFEngine Enterprise +* Linux, macOS, Windows, Unix (and other names of operating systems) +* Mission Portal +* UI, CVE, TCP, TLS, API, HTTP, JSON (and other abbreviations) + +### Titles and verb tenses + +Avoid imperative tense in titles. +Use `-ing` or nouns instead, some examples: + +* What not to do: + * "Write policy" + * "Manage packages" + * "Install CFEngine" + * "Get started" +* Titles you can use instead: + * "Policy writing" (or "Writing policy") + * "Package management" (or "Managing packages") + * "CFEngine installation" (or "Installing CFEngine") + * "Getting started" + +Since anything can be managed, "managing" tends to be used a lot. +Try to use other words: "editing", "updating", "changing", "creating", "setting". + +## Documentation structure ### Structure @@ -209,7 +242,7 @@ expression `begin_rx`, and injects all lines **verbatim** from there until the first line that matches `end_rx`. If `end_rx` is omitted, all lines until the end of the file will be injected. -#### Documenting Policy Libraries +#### Documenting policy libraries * `[%CFEngine_library_include(filename)%]` @@ -247,7 +280,7 @@ will be emitted. All comments before the first doxygen-style tag will be ignored. -#### Documenting CFEngine Syntax Elements +#### Documenting CFEngine syntax elements The following macros require the syntax map to be generated via `cf-promises -s` into a file `syntax_map.json` within the @@ -344,7 +377,7 @@ Renders a table of built-in functions, grouped by function category. Renders a nested tree of CFEngine words, starting at `subtree`. -#### Other Macros +#### Other macros * `[%CFEngine_redirect(target)]` @@ -352,7 +385,7 @@ Injects javascript that redirects the current page to the HTML page for `target` which needs to be a title or title#section combination as in regular `[text][title#section]` links. -## Content Style Guide +## Content style guide Make sure you follow this style guide to make using CFEngine and the documentation a consistent and pleasant experience. @@ -429,7 +462,7 @@ As a general note, avoiding abbreviations provides better readability. ## Technical reference documentation -* follow the [Policy Style Guide](guide/writing-and-serving-policy/policy-style.markdown) +* follow the [Policy style guide](guide/writing-and-serving-policy/policy-style.markdown) in examples and code snippets * use the appropriate lexer for syntax highlighting via Pygments @@ -443,7 +476,7 @@ As a general note, avoiding abbreviations provides better readability. The structure of the technical documentation about CFEngine attributes, functions etc is as follows: -### Promise Attributes +### Promise attributes Promise attributes are documented within the respective promise types's reference page. Level-3 headers are used to start a new attribute (if the promise attribute @@ -571,9 +604,9 @@ use the macro, and list the attributes explicitly: This argument does that. -### Special Variables +### Special variables -Special Variables are documented within the page of their context. +Special variables are documented within the page of their context. ### context.variable diff --git a/api.markdown b/api.markdown index dab3e9bbe..9c3bafa32 100644 --- a/api.markdown +++ b/api.markdown @@ -3,7 +3,6 @@ layout: default title: API published: true sorting: 50 -tags: [overviews, enterprise, REST, API, reporting] --- The CFEngine Enterprise API allows HTTP clients to interact with the @@ -16,4 +15,4 @@ API uses SQL. With the simplicity of REST and the flexibility of SQL, users can craft custom reports about systems of arbitrary scale, mining a wealth of data residing on globally distributed CFEngine Database Servers. -See also the [Enterprise API Examples][Enterprise API Examples] and the [Enterprise API Reference][Enterprise API Reference]. +See also the [Enterprise API examples][Enterprise API examples] and the [Enterprise API reference][Enterprise API reference]. diff --git a/api/enterprise-api-architecture-overview.png b/api/enterprise-api-architecture-overview.png index 9ab9b7055..d963d98f0 100644 Binary files a/api/enterprise-api-architecture-overview.png and b/api/enterprise-api-architecture-overview.png differ diff --git a/api/enterprise-api-examples.markdown b/api/enterprise-api-examples.markdown index 75a187043..b985f046e 100644 --- a/api/enterprise-api-examples.markdown +++ b/api/enterprise-api-examples.markdown @@ -1,17 +1,16 @@ --- layout: default -title: Enterprise API Examples +title: Enterprise API examples published: true sorting: 6 -tags: [examples, enterprise, REST, API, reporting] --- -* [Check installation status][Checking Status] -* [Manage users, roles][Managing Users and Roles] -* [Managing Settings][Managing Settings] -* [Browse host information][Browsing Host Information] -* [Issue flexible SQL queries][SQL Query Examples] against data collected from hosts by the CFEngine Server -* [Schedule reports][SQL Query Examples#Subscribed Query Example: Creating A Subscribed Query] for email and later download +* [Check installation status][Checking status] +* [Manage users, roles][Managing users and roles] +* [Managing settings][Managing settings] +* [Browse host information][Browsing host information] +* [Issue flexible SQL queries][SQL query examples] against data collected from hosts by the CFEngine Server +* [Schedule reports][SQL query examples#Subscribed query example: Creating a subscribed query] for email and later download * [Tracking changes performed by CFEngine][Tracking changes] -**See also:** [Enterprise API Reference][Enterprise API Reference] +**See also:** [Enterprise API reference][Enterprise API reference] diff --git a/api/enterprise-api-examples/browsing-host-information.markdown b/api/enterprise-api-examples/browsing-host-information.markdown index 4f2249cb9..dc6cedf43 100644 --- a/api/enterprise-api-examples/browsing-host-information.markdown +++ b/api/enterprise-api-examples/browsing-host-information.markdown @@ -1,18 +1,17 @@ --- layout: default -title: Browsing Host Information +title: Browsing host information published: true sorting: 50 -tags: [examples, enterprise, rest, api, reporting, hosts] --- A resource [/api/host][Host REST API#List hosts] is added as an alternative interface for browsing host -information. For full flexibility we recommend using [SQL][SQL Schema] +information. For full flexibility we recommend using [SQL][SQL schema] reports via [/api/query][Query REST API#Execute SQL query] for this. however, currently vital signs (data gathered from `cf-monitord`) is not part of the SQL reports data model. -## Example: Listing Hosts With A Given Context +## Example: Listing hosts with a given context **Request** @@ -41,7 +40,7 @@ gathered from `cf-monitord`) is not part of the SQL reports data model. ] } -## Example: Looking Up Hosts By Hostname +## Example: Looking up hosts by hostname Contexts, also known as classes, are powerful. You can use them to categorize hosts according to a rich set of tags. For example, each @@ -74,7 +73,7 @@ for presentability). } -#### Example: Looking Up Hosts By IP +#### Example: Looking up hosts by IP Similarly we can lookup the host with hostname `windows2008-2.test.cfengine.com` by IP as follows (lines split and indented @@ -104,7 +103,7 @@ for presentability). } -## Example: Removing Host Data +## Example: Removing host data If a host has been decommissioned from a Hub, we can explicitly remove data associated with the host from the Hub, by issuing a DELETE request (lines @@ -123,7 +122,7 @@ SHA=1c8fafe478e05eec60fe08d2934415c81a51d2075aac27c9936e19012d625cb8 -X DELETE **See also:** [Host REST API][Host REST API#remove host from the hub] -## Example: Listing Available Vital Signs For A Host +## Example: Listing available vital signs for a host Each host record on the Hub has a set of vital signs collected by `cf-monitord` on the agent. We can view the list of vitals signs from as host as follows @@ -172,7 +171,7 @@ SHA=4e913e2f5ccf0c572b9573a83c4a992798cee170f5ee3019d489a201bc98a1a/vital }, } -## Example: Retrieving Vital Sign Data +## Example: Retrieving vital sign data Each vital sign has a collected time series of values for up to one week. Here we retrieve the time series for the `mem_free` vital sign at host diff --git a/api/enterprise-api-examples/changes-api-usage.markdown b/api/enterprise-api-examples/changes-api-usage.markdown index 8aa09e955..355408a11 100644 --- a/api/enterprise-api-examples/changes-api-usage.markdown +++ b/api/enterprise-api-examples/changes-api-usage.markdown @@ -3,7 +3,6 @@ layout: default title: Tracking changes published: true sorting: 50 -tags: [examples, enterprise, rest, api, reporting, hosts, changes, repairs] --- Changes REST API allows to track the changes made by cf-agent in the infrastructure. diff --git a/api/enterprise-api-examples/checking-status.markdown b/api/enterprise-api-examples/checking-status.markdown index 3e41d3610..9b661da4b 100644 --- a/api/enterprise-api-examples/checking-status.markdown +++ b/api/enterprise-api-examples/checking-status.markdown @@ -1,12 +1,11 @@ --- layout: default -title: Checking Status +title: Checking status published: true sorting: 20 -tags: [examples, enterprise, rest, api, reporting, status] --- -You can get basic info about the API by issuing [/api][Status and Settings REST API#Get server status]. This status +You can get basic info about the API by issuing [/api][Status and settings REST API#Get server status]. This status information may also be useful if you contact support, as it gives some basic diagnostics. diff --git a/api/enterprise-api-examples/managing-settings.markdown b/api/enterprise-api-examples/managing-settings.markdown index fdfaed0ff..ae55781a9 100644 --- a/api/enterprise-api-examples/managing-settings.markdown +++ b/api/enterprise-api-examples/managing-settings.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Managing Settings +title: Managing settings published: true sorting: 30 -tags: [examples, enterprise, rest, api, reporting, settings, ldap] --- Settings support two operations, **GET** (view settings) and **POST** @@ -49,7 +48,7 @@ are managed by the LDAP API and not this Settings API. 204 No Content -## Example: Changing The Log Level +## Example: Changing the log level The API uses standard Unix syslog to log a number of events. Additionally, log events are sent to `stderr`, which means they may also end up in your Apache diff --git a/api/enterprise-api-examples/managing-users-and-roles.markdown b/api/enterprise-api-examples/managing-users-and-roles.markdown index d8a95ba98..c97d56296 100644 --- a/api/enterprise-api-examples/managing-users-and-roles.markdown +++ b/api/enterprise-api-examples/managing-users-and-roles.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Managing Users and Roles +title: Managing users and roles published: true sorting: 40 -tags: [examples, enterprise, rest, api, reporting, users, roles] --- Users and Roles determine who has access to what data from the API. @@ -11,7 +10,7 @@ Roles are defined by regular expressions that determine which hosts the user can see, and what policy outcomes are restricted. -## Example: Listing Users +## Example: Listing users **Request** @@ -47,7 +46,7 @@ user can see, and what policy outcomes are restricted. } -## Example: Creating a New User +## Example: Creating a new user All users will be created for the internal user table. The API will never attempt to write to an external LDAP server. @@ -68,7 +67,7 @@ attempt to write to an external LDAP server. } -## Example: Updating an Existing User +## Example: Updating an existing user Both internal and external users may be updated. When updating an external users, the API will essentially annotate metadata for the user, it will never @@ -84,7 +83,7 @@ credentials. 204 No Content -## Example: Retrieving a User +## Example: Retrieving a user It is possible to retrieve data on a single user instead of listing everything. The following query is similar to issuing `GET @@ -116,7 +115,7 @@ a regular expression for `id`. ] } -## Example: Adding a User to a Role +## Example: Adding a user to a role Adding a user to a role is just an update operation on the user. The full role-set is updated, so if you are only appending a role, you may want to @@ -138,7 +137,7 @@ is used to remove a user from a role. } -## Example: Deleting a User +## Example: Deleting a user Users can only be deleted from the internal users table. diff --git a/api/enterprise-api-examples/sql-queries.markdown b/api/enterprise-api-examples/sql-queries.markdown index 4a86280f6..5641ef2d6 100644 --- a/api/enterprise-api-examples/sql-queries.markdown +++ b/api/enterprise-api-examples/sql-queries.markdown @@ -1,11 +1,10 @@ --- layout: default -title: SQL Query Examples +title: SQL query examples published: true -tags: [examples, enterprise, rest, api, reporting, sql, queries] --- -### Synchronous Example: Listing Hostname and IP for Ubuntu Hosts +### Synchronous Example: Listing hostname and IP for Ubuntu hosts **Request:** @@ -57,7 +56,7 @@ curl -k --user admin:admin https://test.cfengine.com/api/query -X POST -d '{ "qu } ``` -### Subscribed Query Example: Creating A Subscribed Query +### Subscribed query example: Creating a subscribed query Here we create a new query to count file changes by name and have the result sent to us by email. The schedule field is any CFEngine context expression. @@ -79,7 +78,7 @@ curl -k --user admin:admin https://test.cfengine.com/api/user/milton/ subscripti 204 No Content ``` -### Subscribed Query Example: Listing Report Subscriptions +### Subscribed query example: Listing report subscriptions Milton can list all his current subscriptions by issuing the following. @@ -115,7 +114,7 @@ curl -k --user admin:admin https://test.cfengine.com/api/user/milton/subscriptio } ``` -### Subscribed Query Example: Removing A Report Subscription +### Subscribed query example: Removing a report subscription **Request:** diff --git a/api/enterprise-api-ref.markdown b/api/enterprise-api-ref.markdown index aebe9074b..7b40be442 100644 --- a/api/enterprise-api-ref.markdown +++ b/api/enterprise-api-ref.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Enterprise API Reference +title: Enterprise API reference published: true sorting: 70 -tags: [reference, enterprise, REST, API, reporting, sql] --- The Enterprise API is a conventional REST API in the sense that it has a @@ -11,17 +10,17 @@ number of URI resources that support one or more GET, PUT, POST, or DELETE operations. While reporting is done using SQL, this query is always wrapped in a JSON request. -**See also:** [Enterprise API Examples][Enterprise API Examples] +**See also:** [Enterprise API examples][Enterprise API examples] ## Requests **GET** requests are one of **listing** or **getting**. **Listing** resources means that a number of results will be returned, but each entry may contain -limited information. An example of a **listing** query is [/api/user][Users and Access-Control REST API#List users] to list +limited information. An example of a **listing** query is [/api/user][Users and access-control REST API#List users] to list users. Notice that URI components are always non-plural. An exception to this -is [/api/settings][Status and Settings REST API#Get settings], which returns the singleton resource for settings. +is [/api/settings][Status and settings REST API#Get settings], which returns the singleton resource for settings. **Getting** a resource specifies an individual resource to return, e.g. -[/api/user/homer][Users and Access-Control REST API#Get user data]. +[/api/user/homer][Users and access-control REST API#Get user data]. **PUT** request typically create a new resource, e.g. a user. @@ -86,9 +85,9 @@ All timestamps are reported in *Unix Time*, i.e. seconds since 1970. The API supports both internal and external authentication. The internal users table will always be consulted first, followed by an external source specified in the settings. External sources are *OpenLDAP* or *Active Directory* servers -configurable through [/api/settings][Status and Settings REST API#Update settings]. +configurable through [/api/settings][Status and settings REST API#Update settings]. ## Authorization -Some resources require that the request user is a member of the *admin* role. Roles are managed with [/api/role][Users and Access-Control REST API#List RBAC roles]. Role Based Access Control (RBAC) is configurable through the settings. Users typically have permission to access their own resources, e.g. their own scheduled reports. +Some resources require that the request user is a member of the *admin* role. Roles are managed with [/api/role][Users and access-control REST API#List RBAC roles]. Role Based Access Control (RBAC) is configurable through the settings. Users typically have permission to access their own resources, e.g. their own scheduled reports. diff --git a/api/enterprise-api-ref/actions-api.markdown b/api/enterprise-api-ref/actions-api.markdown index ace75e0fd..a793d962a 100644 --- a/api/enterprise-api-ref/actions-api.markdown +++ b/api/enterprise-api-ref/actions-api.markdown @@ -2,7 +2,6 @@ layout: default title: Actions API published: true -tags: [reference, enterprise, API, report collection] --- Actions API enables you to perform specific actions such a requesting report collection. diff --git a/api/enterprise-api-ref/build-api.markdown b/api/enterprise-api-ref/build-api.markdown index 023ce1987..89615034b 100644 --- a/api/enterprise-api-ref/build-api.markdown +++ b/api/enterprise-api-ref/build-api.markdown @@ -2,16 +2,15 @@ layout: default title: Build API published: true -tags: [reference, enterprise, API, build, modules] --- The Build API enables you to easily manage policy projects and their respective CFEngine Build modules. -# Projects API +## Projects API A project is a set of CFEngine Build modules and custom files/json/policy files. -## Create project +### Create project **URI:** https://hub.cfengine.com/api/build/projects @@ -82,7 +81,7 @@ HTTP 200 Ok | 422 Unprocessable entity | Validation error occurred | | 500 Internal server error | Internal server error | -## Update project +### Update project By changing the repository url or branch you will initialize a new project and the current one will be removed from the file system and any un-pushed/un-deployed(terminology in Mission Portal UI) changes will be lost. @@ -150,7 +149,7 @@ HTTP 200 OK | 422 Unprocessable entity | Validation error occurred | | 500 Internal server error | Internal server error | -## Get project +### Get project **URI:** https://hub.cfengine.com/api/build/projects/:id @@ -199,7 +198,7 @@ HTTP 200 OK | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## Get projects list +### Get projects list **URI:** https://hub.cfengine.com/api/build/projects @@ -270,7 +269,7 @@ HTTP 200 OK | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## Delete project +### Delete project **URI:** https://hub.cfengine.com/api/build/projects/:id @@ -303,7 +302,7 @@ HTTP 204 No content | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## Sync project +### Sync project **URI:** https://hub.cfengine.com/build/projects/:id/sync @@ -346,7 +345,7 @@ HTTP 204 No content | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## Refresh project +### Refresh project Fetch upstream repository and return the current state. @@ -395,7 +394,7 @@ HTTP 200 OK | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## List of CFEngine Build modules added to project +### List of CFEngine Build modules added to project **URI:** https://hub.cfengine.com/api/build/projects/:id/modules @@ -469,7 +468,7 @@ HTTP 200 OK | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## Add CFEngine Build module to project +### Add CFEngine Build module to project **URI:** https://hub.cfengine.com/api/build/projects/:id/modules/:module @@ -512,7 +511,7 @@ HTTP 201 Created | 422 Unprocessable entity | Validation error occurred | | 500 Internal server error | Internal server error | -## Delete CFEngine Build module from project +### Delete CFEngine Build module from project **URI:** https://hub.cfengine.com/api/build/projects/:id/modules/:module @@ -547,7 +546,7 @@ HTTP 204 No content | 404 Not found | Project not found | | 500 Internal server error | Internal server error | -## Update CFEngine Build module version +### Update CFEngine Build module version **URI:** https://hub.cfengine.com/api/build/projects/:id/modules/:module @@ -590,7 +589,7 @@ HTTP No content | 422 Unprocessable entity | Validation error occurred | | 500 Internal server error | Internal server error | -## Get list of available CFEngine Build modules +### Get list of available CFEngine Build modules **URI:** https://hub.cfengine.com/api/build/modules @@ -674,7 +673,7 @@ HTTP 200 OK | 200 Ok | Successful response | | 500 Internal server error | Internal server error | -## Update list of available CFEngine Build modules +### Update list of available CFEngine Build modules Modules will be received from the official CFEngine Build modules catalogue https://build.cfengine.com @@ -703,7 +702,7 @@ curl --user : \ | 204 No content | Modules list successfully updated | | 500 Internal server error | Internal server error | -## Get CFEngine build module by name +### Get CFEngine build module by name **URI:** https://hub.cfengine.com/api/build/modules/:name @@ -767,7 +766,7 @@ HTTP 200 OK | 404 Not found | Module not found | | 500 Internal server error | Internal server error | -## Get specific version of a CFEngine Build module by name +### Get specific version of a CFEngine Build module by name **URI:** https://hub.cfengine.com/api/build/modules/:name/:version/ @@ -835,7 +834,7 @@ HTTP 200 OK | 500 Internal server error | Internal server error | -## Get CFEngine Build module input data +### Get CFEngine Build module input data **URI:** https://hub.cfengine.com/api/build/projects/:id/modules/:name/input @@ -913,7 +912,7 @@ HTTP 200 OK | 500 Internal server error | Internal server error | -## Set CFEngine Build module input data +### Set CFEngine Build module input data **URI:** https://hub.cfengine.com/api/build/projects/:id/modules/:name/input diff --git a/api/enterprise-api-ref/changes.markdown b/api/enterprise-api-ref/changes.markdown index 083ebcf12..cbae5c2c0 100644 --- a/api/enterprise-api-ref/changes.markdown +++ b/api/enterprise-api-ref/changes.markdown @@ -2,7 +2,6 @@ layout: default title: Changes REST API published: true -tags: [reference, enterprise, REST, API, reporting, changes, repairs] --- **Changes API** allows to track changes performed by CFEngine agent in the infrastructure. @@ -162,7 +161,7 @@ List changes performed by CFEngine to the infrastructure. List can be narrowed d * **data.hostkey** Unique host identifier. * **data.hostname** - Host name locally detected on the host, configurable as `hostIdentifier` option in [Settings API][Status and Settings REST API#Get settings] and Mission Portal settings UI. + Host name locally detected on the host, configurable as `hostIdentifier` option in [Settings API][Status and settings REST API#Get settings] and Mission Portal settings UI. * **data.logmessages** List of 5 last messages generated during promise execution. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. * **data.policyfile** @@ -174,7 +173,7 @@ List changes performed by CFEngine to the infrastructure. List can be narrowed d * **data.promiser** Object affected by a promise. * **data.promisetype** - [Type][Promise Types] of the promise. + [Type][Promise types] of the promise. * **data.stackpath** Call stack of the promise. diff --git a/api/enterprise-api-ref/cmdb-api.markdown b/api/enterprise-api-ref/cmdb-api.markdown index 88500ac4e..5c728d8d0 100644 --- a/api/enterprise-api-ref/cmdb-api.markdown +++ b/api/enterprise-api-ref/cmdb-api.markdown @@ -2,7 +2,6 @@ layout: default title: CMDB API published: true -tags: [reference, enterprise, API, CMDB, classes, variables] --- The configuration management database (CMDB) API enables you to manage classes and variables for specific hosts. diff --git a/api/enterprise-api-ref/export-import-api.markdown b/api/enterprise-api-ref/export-import-api.markdown index 4c694268f..fc88f61d2 100644 --- a/api/enterprise-api-ref/export-import-api.markdown +++ b/api/enterprise-api-ref/export-import-api.markdown @@ -1,13 +1,12 @@ --- layout: default -title: Import & Export API +title: Import & export API published: true -tags: [reference, enterprise, API, import, export] --- -Import & Export API provides users the ability to transfer Mission Portal data between hubs. +Import & export API provides users the ability to transfer Mission Portal data between hubs. -**See also:** [Export/Import Settings UI][Settings#Export/Import] +**See also:** [Export/import Settings UI][Settings#Export/import] ## Get available items to export @@ -91,7 +90,7 @@ HTTP 200 Ok * **item_id** *(array)* Item id to be exported. - List of item ids you can obtain through [List of items to export][Import & Export API#Get available items to export] + List of item ids you can obtain through [List of items to export][Import & export API#Get available items to export] call described below. * **encryptionKey** *(string)* @@ -221,7 +220,7 @@ curl -k --user : \ -F file=@/path/to/file.phar \ -F encryptionKey=key \ -F skipDuplicates=1 \ -'https://hub.example/index.php/data_transfer/api/analyzeImportFile' +'https://hub.example/index.php/data_transfer/api/import' ``` **Example response:** diff --git a/api/enterprise-api-ref/export-import-compliance-report-api.markdown b/api/enterprise-api-ref/export-import-compliance-report-api.markdown index 069ba7afd..ff48aae73 100644 --- a/api/enterprise-api-ref/export-import-compliance-report-api.markdown +++ b/api/enterprise-api-ref/export-import-compliance-report-api.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Import & Export Compliance Report API +title: Import & export compliance report API published: true -tags: [reference, enterprise, API, import, export, compliance report] --- This provides users the ability to transfer compliance reports between hubs or create reports from a JSON definition file. diff --git a/api/enterprise-api-ref/federated-reporting-api.markdown b/api/enterprise-api-ref/federated-reporting-api.markdown index 0bc246835..1a36ab1fe 100644 --- a/api/enterprise-api-ref/federated-reporting-api.markdown +++ b/api/enterprise-api-ref/federated-reporting-api.markdown @@ -2,17 +2,16 @@ layout: default title: Federated reporting configuration API published: true -tags: [reference, enterprise, API, reporting] --- This API is used for configuring hubs so that a single hub can be used to report on any host connected to participating feeder hubs. -# Remote hubs +## Remote hubs Federated reporting must be enabled before it is possible to use the remote hubs API, please -see the `Enable hub for Federated Reporting` section below. +see the `Enable hub for federated reporting` section below. -## Remote hubs list +### Remote hubs list **URI:** https://hub.cfengine.com/api/fr/remote-hub @@ -56,7 +55,7 @@ HTTP 200 OK } ``` -## Get remote hub +### Get remote hub **URI:** https://hub.cfengine.com/api/fr/remote-hub/:remote_hub_id @@ -88,7 +87,7 @@ HTTP 200 OK } ``` -## Add remote hub +### Add remote hub **URI:** https://hub.cfengine.com/api/fr/remote-hub @@ -113,7 +112,7 @@ HTTP 200 OK HTTP 201 CREATED ``` -## Update remote hub +### Update remote hub **URI:** https://hub.cfengine.com/api/fr/remote-hub/:remote_hub_id @@ -140,7 +139,7 @@ HTTP 201 CREATED HTTP 202 ACCEPTED ``` -## Delete remote hub +### Delete remote hub **URI:** https://hub.cfengine.com/api/fr/remote-hub/:remote_hub_id @@ -157,9 +156,9 @@ HTTP 202 ACCEPTED HTTP 202 ACCEPTED ``` -# Enable hub for Federated Reporting +## Enable hub for federated reporting -## Enable hub as a Superhub +### Enable hub as a superhub **URI:** https://hub.cfengine.com/api/fr/setup-hub/superhub @@ -172,7 +171,7 @@ HTTP 202 ACCEPTED ``` -## Enable hub as a Feeder +### Enable hub as a feeder **URI:** https://hub.cfengine.com/api/fr/setup-hub/feeder @@ -184,7 +183,7 @@ HTTP 202 ACCEPTED HTTP 202 ACCEPTED ``` -## Hub status +### Hub status **URI:** https://hub.cfengine.com/api/fr/hub-status @@ -203,13 +202,13 @@ HTTP 202 ACCEPTED } ``` -# Federation config +## Federation config Federated reporting must be enabled before generating or removing federation configuration, please -see `Enable hub for Federated Reporting` section above. Otherwise an error will be thrown and +see `Enable hub for federated reporting` section above. Otherwise an error will be thrown and config file will not be created/deleted. -## Generate federation config +### Generate federation config **URI:** https://hub.cfengine.com/api/fr/federation-config @@ -221,7 +220,7 @@ config file will not be created/deleted. HTTP 202 ACCEPTED ``` -## Delete federation config +### Delete federation config **URI:** https://hub.cfengine.com/api/fr/federation-config diff --git a/api/enterprise-api-ref/file-changes.markdown b/api/enterprise-api-ref/file-changes.markdown index a3addfbd9..799729b1f 100644 --- a/api/enterprise-api-ref/file-changes.markdown +++ b/api/enterprise-api-ref/file-changes.markdown @@ -1,8 +1,7 @@ --- layout: default -title: File Changes API +title: File changes API published: true -tags: [reference, enterprise, API, reporting, file changes] --- diff --git a/api/enterprise-api-ref/health-diagnostic.markdown b/api/enterprise-api-ref/health-diagnostic.markdown index feaeae3e2..0bac189d1 100644 --- a/api/enterprise-api-ref/health-diagnostic.markdown +++ b/api/enterprise-api-ref/health-diagnostic.markdown @@ -2,7 +2,6 @@ layout: default title: Health diagnostic API published: true -tags: [reference, enterprise, API, reporting, URI, health] --- This API provides access to health diagnostic information. diff --git a/api/enterprise-api-ref/host.markdown b/api/enterprise-api-ref/host.markdown index 43eee7f1a..32e4180a6 100644 --- a/api/enterprise-api-ref/host.markdown +++ b/api/enterprise-api-ref/host.markdown @@ -2,7 +2,6 @@ layout: default title: Host REST API published: true -tags: [reference, enterprise, REST, API, reporting, host, monitoring] --- Host API allows to access host specific information. @@ -60,7 +59,7 @@ Host API allows to access host specific information. * **id** Unique host identifier. * **hostname** - Host name. Can be reconfigured globally to represent variable set in the policy using **hostIdentifier** [setting][Status and Settings REST API#Update settings]. + Host name. Can be reconfigured globally to represent variable set in the policy using **hostIdentifier** [setting][Status and settings REST API#Update settings]. * **ip** IP address of the host. If host have multiple network interfaces, IP belongs to the interface that is used to communicate with policy server. * **lastreport** @@ -68,9 +67,9 @@ Host API allows to access host specific information. * **firstseen** Time of receiving the first status report from the client. It is equivalent to the time when the client have been bootstrapped to the server for the first time. Represented as UNIX TIMESTAMP. -**Example usage:** `Example: Listing Hosts With A Given Context`, `Example: Looking Up Hosts By Hostname`, `Example: Looking Up Hosts By IP` +**Example usage:** `Example: Listing hosts with a given context`, `Example: Looking up hosts by hostname`, `Example: Looking up hosts by IP` -## Host Details +## Host details **URI:** https://hub.cfengine.com/api/host/:host-id @@ -103,7 +102,7 @@ Host API allows to access host specific information. * **id** Unique host identifier. * **hostname** - Host name. Can be reconfigured globally to represent variable set in the policy using **hostIdentifier** [setting][Status and Settings REST API#Update settings]. + Host name. Can be reconfigured globally to represent variable set in the policy using **hostIdentifier** [setting][Status and settings REST API#Update settings]. * **ip** IP address of the host. If host have multiple network interfaces, IP belongs to the interface that is used to communicate with policy server. * **lastreport** @@ -139,7 +138,7 @@ The hostkey is then removed from: Note: There is a record of the host retained that includes the time when the host was deleted and this record also prevents further collection from this host identity. -**See also:** [Example removing host data][Browsing Host Information#example: removing host data] +**See also:** [Example removing host data][Browsing host information#example: removing host data] ## Hosts list grouped by hard classes @@ -357,7 +356,7 @@ Note: Collecting monitoring data by default is disabled. * **units** Units for the samples. -**Example usage:** `Example: Listing Available Vital Signs For A Host` +**Example usage:** `Example: Listing available vital signs for a host` ## Get samples from vital @@ -420,7 +419,7 @@ Note: Collecting monitoring data by default is disabled. * **values** Vital sign data. *(array of [ t, y ], where t is the sample timestamp)* -**Example usage:** `Example: Retrieving Vital Sign Data` +**Example usage:** `Example: Retrieving vital sign data` ## Get count of bootstrapped hosts by date range diff --git a/api/enterprise-api-ref/inventory.markdown b/api/enterprise-api-ref/inventory.markdown index 43419ce70..574d656c5 100644 --- a/api/enterprise-api-ref/inventory.markdown +++ b/api/enterprise-api-ref/inventory.markdown @@ -2,11 +2,10 @@ layout: default title: Inventory API published: true -tags: [reference, enterprise, API, reporting, URI] --- Inventory API allows to access inventory reports and attributes dictionary. -## Inventory Reports +## Inventory reports **URI:** https://hub.cfengine.com/api/inventory @@ -188,7 +187,7 @@ curl -k --user : \ Shows list of all inventory attributes available in the system. See more details: -* [Custom Inventory][Custom Inventory] +* [Custom inventory][Custom inventory] **CURL request example** ``` diff --git a/api/enterprise-api-ref/ldap-api.markdown b/api/enterprise-api-ref/ldap-api.markdown index 6fcc04a89..2c3276ab3 100644 --- a/api/enterprise-api-ref/ldap-api.markdown +++ b/api/enterprise-api-ref/ldap-api.markdown @@ -2,7 +2,6 @@ layout: default title: LDAP authentication API published: true -tags: [reference, enterprise, API, authenticating, LDAP] --- LDAP authentication API allows to check ldap user credentials and change LDAP settings. diff --git a/api/enterprise-api-ref/query.markdown b/api/enterprise-api-ref/query.markdown index 102988604..8f39e35e4 100644 --- a/api/enterprise-api-ref/query.markdown +++ b/api/enterprise-api-ref/query.markdown @@ -2,12 +2,11 @@ layout: default title: Query REST API published: true -tags: [reference, enterprise, REST, API, SQL, reporting, URI] --- In case of a need for full flexibility, Query API allow users to execute SQL queries on CFEngine Database. -Database schema available can be found [here][SQL Schema]. +Database schema available can be found [here][SQL schema]. ## Execute SQL query @@ -87,7 +86,7 @@ API performance depend on the query result size, to achieve fastest results cons } ``` -**Example usage:** `Synchronous Example: Listing Hostname and IP for Ubuntu Hosts` +**Example usage:** `Synchronous Example: Listing hostname and IP for Ubuntu hosts` ## Schedule SQL query as long running job diff --git a/api/enterprise-api-ref/sql-schema.markdown b/api/enterprise-api-ref/sql-schema.markdown index efa653ef8..1d96578e4 100644 --- a/api/enterprise-api-ref/sql-schema.markdown +++ b/api/enterprise-api-ref/sql-schema.markdown @@ -1,1782 +1,11 @@ --- layout: default -title: SQL Schema +title: SQL schema published: true -tags: [reference, enterprise, REST, API, reporting, sql, schema] --- -CFEngine allows standardized SQL `SELECT` queries to be used with [REST API][Query REST API#Execute SQL query]. -Queries can be used with following database schema. +CFEngine Enterprise uses multiple databases. -```bash -curl -k --user admin:admin https://hub.cfengine.com/api/query -X POST -d "{ \"query\": \"SELECT Hosts.HostName, Hosts.IPAddress FROM Hosts WHERE hostname = 'hub'\"}" -``` - -## Table: AgentStatus - -Agent status contains information about last cf-agent execution. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **AgentExecutionInterval** *(integer)* - Estimated interval in which cf-agent is being executed, as cf-agent execution interval is expressed in CFEngine context expressions (Min00_05 etc.) it can be not regular, this interval is discovered by analyzing last few cf-agent execution timestamps. Expressed in seconds. - -* **LastAgentLocalExecutionTimeStamp** *(timestamp)* - Timestamp of last cf-agent execution on the host. - -* **LastAgentExecutionStatus** *(`OK`/`FAIL`)* - cf-agent execution status. In case cf-agent will not execute within 3x `AgentExecutionInterval` from last execution, status will be set to `FAIL`. Failure may indicate cf-execd issues, or cf-agent crashes. - -**Example query:** - -```sql -SELECT hostkey, - agentexecutioninterval, - lastagentlocalexecutiontimestamp, - lastagentexecutionstatus -FROM agentstatus; -``` - -**Output:** - -``` --[ RECORD 1 ]--------------------|----------------------- -hostkey | SHA=3b94d... -agentexecutioninterval | 277 -lastagentlocalexecutiontimestamp | 2015-03-11 12:37:39+00 -lastagentexecutionstatus | OK --[ RECORD 2 ]--------------------|----------------------- -hostkey | SHA=a4dd5... -agentexecutioninterval | 275 -lastagentlocalexecutiontimestamp | 2015-03-11 12:36:36+00 -lastagentexecutionstatus | OK --[ RECORD 3 ]--------------------|----------------------- -hostkey | SHA=2aab8... -agentexecutioninterval | 284 -lastagentlocalexecutiontimestamp | 2015-03-11 12:36:51+00 -lastagentexecutionstatus | OK -``` - -## Table: BenchmarksLog - -Data from internal cf-agent monitoring as also [measurements promises][measurements]. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **EventName** *(text)* - Name of measured event. - -* **StandardDeviation** *(numeric)* - Dispersion of a set of data from its mean. - -* **AverageValue** *(numeric)* - Average value. - -* **LastValue** *(numeric)* - Last measured value. - -* **CheckTimeStamp** *(timestamp)* - Measurement time. - -**Example query:** - -```sql -SELECT hostkey, - eventname, - standarddeviation, - averagevalue, - lastvalue, - checktimestamp -FROM benchmarkslog; -``` - -**Output:** - -``` --[ RECORD 1 ]-----|-------------------------------------------------------- -hostkey | SHA=3b94d... -eventname | CFEngine Execution ('/var/cfengine/inputs/promises.cf') -standarddeviation | 7.659365 -averagevalue | 3.569665 -lastvalue | 1.170841 -checktimestamp | 2015-03-10 14:08:12+00 --[ RECORD 2 ]---=-|-------------------------------------------------------- -hostkey | SHA=3b94d... -eventname | CFEngine Execution ('/var/cfengine/inputs/update.cf') -standarddeviation | 0.131094 -averagevalue | 0.422757 -lastvalue | 0.370686 -checktimestamp | 2015-03-10 14:08:11+00 --[ RECORD 3 ]-----|-------------------------------------------------------- -hostkey | SHA=3b94d... -eventname | DBReportCollectAll -standarddeviation | 0.041025 -averagevalue | 1.001964 -lastvalue | 1.002346 -checktimestamp | 2015-03-10 14:05:20+00 -``` - -## Table: Contexts - -CFEngine contexts present on hosts at their last reported cf-agent execution. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ContextName** *(text)* - CFEngine [context][Classes and Decisions] set by cf-agent. - -* **MetaTags** *(text[])* - List of [meta tags][Tags for variables, classes, and bundles] set for the context. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp since when context is set in its current form. - **Note:** If any of the context attributes change, the timestamp will be updated. - -**Example query:** - -```sql -SELECT hostkey, - contextname, - metatags, - changetimestamp -FROM contexts; -``` - -**Output:** - -``` --[ RECORD 1 ]---|------------------------------------------------------- -hostkey | SHA=a4dd5... -contextname | enterprise_3_6_5 -metatags | {inventory,attribute_name=none,source=agent,hardclass} -changetimestamp | 2015-03-11 09:50:11+00 --[ RECORD 2 ]---|------------------------------------------------------- -hostkey | SHA=a4dd5... -contextname | production -metatags | {report,"Production environment"} -changetimestamp | 2015-03-11 09:50:11+00 --[ RECORD 3 ]---|------------------------------------------------------- -hostkey | SHA=a4dd5... -contextname | enterprise_edition -metatags | {inventory,attribute_name=none,source=agent,hardclass} -changetimestamp | 2015-03-11 09:50:11+00 -``` - -## Table: ContextsLog - -CFEngine contexts set on hosts by CFEngine over period of time. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp since when context is set in its current form. - **Note:** The statement if true till present time or newer entry claims otherwise. - -* **ChangeOperation** *(`ADD`,`CHANGE`,`REMOVE`,`UNTRACKED`)* - CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. - * `ADD` - stands for introducing a new entry which did not exist before. In this case, new CFEngine context have been introduced. - * `CHANGE` - stands for changing value or attribute such as `MetaTags` have changed. - * `REMOVE` - Context have not been set. - * `UNTRACKED` - CFEngine provides a mechanism for filtering unwanted data from being reported. `UNTRACKED` marker states that information about this context is being filtered and will not report any future information about it. - -* **ContextName** *(text)* - CFEngine [context][Classes and Decisions] set by cf-agent. - -* **MetaTags** *(text[])* - List of [meta tags][Tags for variables, classes, and bundles] set for the context. - - -**Example query:** - -```sql -SELECT hostkey, - changetimestamp, - changeoperation, - contextname, - metatags -FROM contextslog; -``` - -**Output:** - -``` --[ RECORD 1 ]---|------------------------------------------------------- -hostkey | SHA=a4dd5... -changetimestamp | 2015-03-10 13:40:20+00 -changeoperation | ADD -contextname | debian -metatags | {inventory,attribute_name=none,source=agent,hardclass} --[ RECORD 2 ]---|------------------------------------------------------- -hostkey | SHA=a4dd5... -changetimestamp | 2015-03-10 14:40:20+00 -changeoperation | ADD -contextname | ipv4_192_168 -metatags | {inventory,attribute_name=none,source=agent,hardclass} --[ RECORD 3 ]---|------------------------------------------------------- -hostkey | SHA=a4dd5... -changetimestamp | 2015-03-10 15:40:20+00 -changeoperation | ADD -contextname | nova_3_6_5 -metatags | {inventory,attribute_name=none,source=agent,hardclass} -``` - -## Table: FileChangesLog - -Log of changes detected to files that are set to be [monitored][files#changes] by cf-agent. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **PromiseHandle** *(text)* - A Uniqueue id-tag string for referring promise. - -* **FileName** *(text)* - Name of the file that have changed. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp when CFEngine have detected the change to the file. - -* **ChangeType** *(text)* - Type of change detected on the monitored file. - * DIFF - change in content (with file diff) - * S - change in file stats - * C - change in content (based on file hash) - -* **ChangeDetails** *(text[])* - Information about changes detected to the file. Such as file stats information, file diff etc. - -**Example query:** - -```sql -SELECT hostkey, - promisehandle, - filename, - changetimestamp, - changetype, - changedetails -FROM filechangeslog; -``` - -**Output:** - -``` --[ RECORD 1 ]---|------------------------------------------------------------ -hostkey | SHA=3b94d... -promisehandle | my_test_promise -filename | /tmp/app.conf -changetimestamp | 2015-03-13 13:16:10+00 -changetype | C -changedetails | {"Content changed"} --[ RECORD 2 ]---|------------------------------------------------------------ -hostkey | SHA=3b94d... -promisehandle | my_test_promise -filename | /tmp/app.conf -changetimestamp | 2015-03-13 13:16:10+00 -changetype | DIFF -changedetails | {"-,1,loglevel = info","+,1,loglevel = debug"} --[ RECORD 3 ]---|------------------------------------------------------------ -hostkey | SHA=3b94d... -promisehandle | my_test_promise -filename | /tmp/app.conf -changetimestamp | 2015-03-09 11:46:36+00 -changetype | S -changedetails | {"Modified time: Mon Mar 9 11:37:50 -> Mon Mar 9 11:42:27"} -``` - -## Table: Hosts - -Hosts table contains basic information about hosts managed by CFEngine. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect - data concerning same hosts. - -* **HostName** *(text)* - Host name locally detected on the host, configurable as `hostIdentifier` - option in [Settings API][Status and Settings REST API#Get settings] and - Mission Portal settings UI. - -* **IPAddress** *(text)* - IP address of the host derived from the lastseen database (this is expected - to be the IP address from which connections come from, beware NAT will cause - multiple hosts to appear to have the same IP address). - -* **LastReportTimeStamp** *(timestamp)* - Timestamp of the most recent successful report collection. - -* **FirstReportTimeStamp** *(timestamp)* - Timestamp when the host reported to the hub for the first time, which - indicate when the host was bootstrapped to the hub. - -**Example query:** - -```sql -SELECT hostkey, - hostname, - ipaddress, - lastreporttimestamp, - firstreporttimestamp -FROM hosts; -``` - -**Output:** - -``` --[ RECORD 1 ]--------|----------------------- -hostkey | SHA=a4dd... -hostname | host001 -ipaddress | 192.168.56.151 -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 --[ RECORD 2 ]--------|----------------------- -hostkey | SHA=3b94... -hostname | hub -ipaddress | 192.168.56.65 -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:34:20+00 --[ RECORD 3 ]--------|----------------------- -hostkey | SHA=2aab... -hostname | host002 -ipaddress | 192.168.56.152 -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 -``` - -## Table: Hosts_not_reported - -Hosts_not_reported table contains information about not reported hosts. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect - data concerning same hosts. - -* **iscallcollected** *(boolean)* - Is host call collected - -* **LastReportTimeStamp** *(timestamp)* - Timestamp of the most recent successful report collection. - -* **FirstReportTimeStamp** *(timestamp)* - Timestamp when the host reported to the hub for the first time, which - indicate when the host was bootstrapped to the hub. - -**Example query:** - -```sql -SELECT hostkey, - iscallcollected, - lastreporttimestamp, - firstreporttimestamp -FROM hosts; -``` - -**Output:** - -``` --[ RECORD 1 ]--------|----------------------- -hostkey | SHA=a4dd... -iscallcollected | t -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 --[ RECORD 2 ]--------|----------------------- -hostkey | SHA=3b94... -iscallcollected | f -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:34:20+00 --[ RECORD 3 ]--------|----------------------- -hostkey | SHA=2aab... -iscallcollected | f -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 -``` - -## Table: HubConnectionErrors - -Networking errors encountered by cf-hub during its operation. - -**Columns:** - -* **HostKey** *(text)* - Unique identifier of the host that cf-hub was connecting to. - -* **CheckTimeStamp** *(timestamp)* - Timestamp when the error occurred. - -* **Message** *(text)* - Error type / message. - -* **QueryType** *(text)* - Type of query that was intended to be sent by hub during failed connection attempt. - -**Example query:** - -```sql -SELECT hostkey, - checktimestamp, - message, - querytype, -FROM hubconnectionErrors; -``` - -**Output:** - -``` --[ RECORD 1 ]--|-------------------------- -hostkey | SHA=3b94d... -checktimestamp | 2015-03-13 13:16:10+00 -message | ServerNoReply -querytype | delta --[ RECORD 2 ]--|-------------------------- -hostkey | SHA=3b94d... -checktimestamp | 2015-03-13 14:16:10+00 -message | InvalidData -querytype | rebase --[ RECORD 3 ]--|-------------------------- -hostkey | SHA=3b94d... -checktimestamp | 2015-03-13 15:16:10+00 -message | ServerAuthenticationError -querytype | delta -``` - -## Table: Inventory - -Inventory data - -**Columns:** - -* **HostKey** *(text)* - Unique identifier of the host. - -* **keyname** *(text)* - Name of the key. - -* **type** *(text)* - Type of the variable. [List][Variables] of supported variable types. - -* **metatags** *(text[])* - List of [meta tags][Tags for variables, classes, and bundles] set for the variable. - -* **value** *(text)* - Variable value serialized to string. - * List types such as: `slist`, `ilist`, `rlist` are serialized with CFEngine list format: {'value','value'}. - * `Data` type is serialized as JSON string. - -**Example query:** - -```sql -SELECT hostkey, - keyname, - type, - metatags, - value -FROM Inventory; -``` - -**Output:** - -``` --[ RECORD 1 ]--|-------------------------- -hostkey | SHA=3b94d... -keyname | default.sys.fqhost -type | string -metatags | {inventory,source=agent,"attribute_name=Host name"} -value | host name --[ RECORD 2 ]--|-------------------------- -hostkey | SHA=3b94d... -keyname | default.sys.uptime -type | int -metatags | {inventory,source=agent,"attribute_name=Uptime minutes"} -value | 4543 -``` - -## Table: Inventory_new - -Inventory data grouped by host - -**Columns:** - -* **HostKey** *(text)* - Unique identifier of the host. - -* **values** *(jsonb)* - Inventory values presented in JSON format - - -**Example query:** - -```sql -SELECT hostkey, - values -FROM Inventory_new; -``` - -**Output:** - -``` --[ RECORD 1 ]--|-------------------------- -hostkey | SHA=3b94d... -values | {"OS": "ubuntu", "OS type": "linux", "CPU model": "CPU model A10", "Host name": "SHA=aa11bb1", "OS kernel": "14.4.0-53-generic", "Interfaces": "pop, imap", "BIOS vendor": "BIOS vendor", "CFEngine ID": "SHA=aa11bb1", "CPU sockets": "229", "New OS type": "linux", "Architecture": "x86_64"} --[ RECORD 2 ]--|-------------------------- -hostkey | SHA=5rt43... -values | {"OS": "ubuntu", "OS type": "linux", "CPU model": "CPU model A10", "Host name": "SHA=aa11bb1", "OS kernel": "14.4.0-53-generic", "Interfaces": "pop, imap", "BIOS vendor": "BIOS vendor", "CFEngine ID": "SHA=aa11bb1", "CPU sockets": "229", "New OS type": "linux", "Architecture": "x86_64"} -``` - -## Table: LastSeenHosts - -Information about communication between CFEngine clients. Effectively a snapshot -of each hosts lastseen database (`cf_lastseen.lmdb`, `cf-key -s`) at the time of -their last reported `cf-agent` execution. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **LastSeenDirection** *(`INCOMING`/`OUTGOING`)* - Direction within which the connection was established. - * `INCOMING` - host received incoming connection. - * `OUTGOING` - host opened connection to remote host. - -* **RemoteHostKey** *(text)* - `HostKey` of the remote host. - -* **RemoteHostIP** *(text)* - IP address of the remote host. - -* **LastSeenTimeStamp** *(timestamp)* - Time when the connection was established. - -* **LastSeenInterval** *(real)* - Average time period (seconds) between connections for the given `LastSeenDirection` with the host. - -**Example query:** - -```sql -SELECT hostkey, - lastseendirection, - remotehostkey, - remotehostip, - lastseentimestamp, - lastseeninterval -FROM lastseenhosts; -``` - -**Output:** - -``` --[ RECORD 1 ]-----|----------------------- -hostkey | SHA=3b94d... -lastseendirection | OUTGOING -remotehostkey | SHA=2aab8... -remotehostip | 192.168.56.152 -lastseentimestamp | 2015-03-13 12:20:45+00 -lastseeninterval | 299 --[ RECORD 2 ]-----|------------------------ -hostkey | SHA=3b94d... -lastseendirection | INCOMING -remotehostkey | SHA=a4dd5... -remotehostip | 192.168.56.151 -lastseentimestamp | 2015-03-13 12:22:06+00 -lastseeninterval | 298 --[ RECORD 3 ]-----|------------------------ -hostkey | SHA=2aab8... -lastseendirection | INCOMING -remotehostkey | SHA=3b94d... -remotehostip | 192.168.56.65 -lastseentimestamp | 2015-03-13 12:20:45+00 -lastseeninterval | 299 -``` - -## Table: LastSeenHostsLogs - -History of LastSeenHosts table - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **LastSeenDirection** *(`INCOMING`/`OUTGOING`)* - Direction within which the connection was established. - * `INCOMING` - host received incoming connection. - * `OUTGOING` - host opened connection to remote host. - -* **RemoteHostKey** *(text)* - `HostKey` of the remote host. - -* **RemoteHostIP** *(text)* - IP address of the remote host. - -* **LastSeenTimeStamp** *(timestamp)* - Time when the connection was established. - -* **LastSeenInterval** *(real)* - Average time period (seconds) between connections for the given `LastSeenDirection` with the host. - -**Example query:** - -```sql -SELECT hostkey, - lastseendirection, - remotehostkey, - remotehostip, - lastseentimestamp, - lastseeninterval -FROM LastSeenHostsLogs; -``` - -**Output:** - -``` --[ RECORD 1 ]-----|----------------------- -hostkey | SHA=3b94d... -lastseendirection | OUTGOING -remotehostkey | SHA=2aab8... -remotehostip | 192.168.56.152 -lastseentimestamp | 2015-03-13 12:20:45+00 -lastseeninterval | 299 --[ RECORD 2 ]-----|------------------------ -hostkey | SHA=3b94d... -lastseendirection | INCOMING -remotehostkey | SHA=a4dd5... -remotehostip | 192.168.56.151 -lastseentimestamp | 2015-03-13 12:22:06+00 -lastseeninterval | 298 --[ RECORD 3 ]-----|------------------------ -hostkey | SHA=2aab8... -lastseendirection | INCOMING -remotehostkey | SHA=3b94d... -remotehostip | 192.168.56.65 -lastseentimestamp | 2015-03-13 12:20:45+00 -lastseeninterval | 299 -``` - -## Table: MonitoringHg - -Stores 1 record for each observable per host. - -**Columns:** - -* **host** *(text)* - Unique host identifier. Referred to in other tables as `HostKey` to connect - data concerning same hosts. - -* **id** *(text)* - Name of monitored metric. The handle of the measurement promise. - -* **ar1** *(real)* - Average across 66 observations. - -## Table: MonitoringMgMeta - -Stores 1 record for each observable per host. - -**Columns:** - -* **id** *(integer)* - Unique identifier for host observable. - -* **hostkey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect - data concerning same hosts. - -* **observable** *(text)* - Name of monitored metric. The handle of the measurement promise. - -* **global** *(boolean)* - -* **expected_min** *(real)* - Minimum expected value. - -* **expected_max** *(real)* - Maximum expected value. - -* **unit** *(text)* - Unit of measurement. - -* **description** *(text)* - Description of unit of measurement. - -* **updatedtimestamp** *(timestamp with time zone)* - Time when measurement sampled. - -* **lastupdatedsample** *(integer)* - Value of most recently collected measurement. - -## Table: MonitoringYrMeta - -Stores 1 record for each observable per host. - -**Columns:** - -* **id** *(integer)* - Unique identifier for host observable. - -* **hostkey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect - data concerning same hosts. - -* **observable** *(text)* - Name of monitored metric. The handle of the measurement promise. - -* **global** *(boolean)* - -* **expected_min** *(real)* - Minimum expected value. - -* **expected_max** *(real)* - Maximum expected value. - -* **unit** *(text)* - Unit of measurement. - -* **description** *(text)* - Description of unit of measurement. - -* **lastupdatedsample** *(integer)* - Value of most recently collected measurement. - -## Table: PromiseExecutions - -Promises executed on hosts during their last reported cf-agent run. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **PolicyFile** *(text)* - Path to the file where the promise is located in. - -* **ReleaseId** *(text)* - Unique identifier of masterfiles version that is executed on the host. - -* **PromiseHash** *(text)* - Unique identifier of a promise. It is a hash of all promise attributes and their values. - -* **NameSpace** *(text)* - [Namespace][Namespaces] within which the promise is executed. If no namespace is set then it is set as: `default`. - -* **BundleName** *(text)* - [Bundle][Bundles] name where the promise is executed. - -* **PromiseType** *(text)* - [Type][Promise Types] of the promise. - -* **Promiser** *(text)* - Object affected by a promise. - -* **StackPath** *(text)* - Call stack of the promise. - -* **PromiseHandle** *(text)* - A unique id-tag string for referring promise. - -* **PromiseOutcome** *(`KEPT`/`NOTKEPT`/`REPAIRED`)* - Promise execution result. - * `KEPT` - System has been found in the state as desired by the promise. CFEngine did not have to do any action to correct the state. - * `REPAIRED` - State of the system differed from the desired state. CFEngine took successful action to correct it according to promise specification. - * `NOTKEPT` - CFEngine has failed to converge the system according to the promise specification. - -* **LogMessages** *(text[])* - List of 5 last messages generated during promise execution. If the promise is `KEPT` the messages are not reported. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. - -* **Promisees** *(text[])* - List of [promisees][Promises] defined for the promise. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp since when the promise is continuously executed by cf-agent in its current configuration and provides the same output. - **Note:** If any of the promise dynamic attributes change, like promise outcome, log messages or the new policy version will be rolled out. This timestamp will be changed. - -**Example query:** - -```sql -SELECT hostkey, - policyfile, - releaseid, - promisehash, - namespace, - bundlename, - promisetype, - promiser, - stackpath, - promisehandle, - promiseoutcome, - logmessages, - promisees, - changetimestamp -FROM softwareupdates; -``` - -**Output:** - -``` --[ RECORD 1 ]---|--------------------------------------------------------- -hostkey | SHA=a4dd5... -policyfile | /var/cfengine/inputs/inventory/any.cf -releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 -promisehash | fd6d5e40b734e35d9e8b2ed071dfe390f23148053adaae3dbb936... -namespace | default -bundlename | inventory_autorun -promisetype | methods -promiser | mtab -stackpath | /default/inventory_autorun/methods/'mtab'[0] -promisehandle | cfe_internal_autorun_inventory_mtab -promiseoutcome | KEPT -logmessages | {} -promisees | {} -changetimestamp | 2015-03-12 10:20:18+00 --[ RECORD 2 ]---|--------------------------------------------------------- -hostkey | SHA=a4dd5... -policyfile | /var/cfengine/inputs/promises.cf -releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 -promisehash | 925b04453ef86ff2e43228a5ca5d56dc4d69ddf12378d6fdba28b... -namespace | default -bundlename | service_catalogue -promisetype | methods -promiser | security -stackpath | /default/service_catalogue/methods/'security'[0] -promisehandle | service_catalogue_change_management -promiseoutcome | KEPT -logmessages | {} -promisees | {goal_infosec,goal_compliance} -changetimestamp | 2015-03-12 10:20:18+00 --[ RECORD 3 ]---|--------------------------------------------------------- -hostkey | SHA=3b94d... -policyfile | /var/cfengine/inputs/lib/3.6/bundles.cf -releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 -promisehash | 47f64d43f21bc6162b4f21bf385e715535617eebc649b259ebaca... -namespace | default -bundlename | logrotate -promisetype | files -promiser | /var/cfengine/cf3.hub.runlog -stackpath | /default/cfe_internal_management/files/'any'/default/... -promisehandle | -promiseoutcome | REPAIRED -logmessages | {"Rotating files '/var/cfengine/cf3.hub.runlog'"} -promisees | {} -changetimestamp | 2015-03-12 14:52:36+00 -``` - -## Table: PromiseExecutionsLog - -**This table was deprecated in 3.7.0. It is no longer used.** - -Promise status / outcome changes over period of time. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp when the promise state or outcome changed. - **Note:** The statement if true till present time or newer entry claims otherwise. - -* **ChangeOperation** *(`ADD`,`CHANGE`,`REMOVE`,`UNTRACKED`)* - CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. - * `ADD` - stands for introducing a new entry which did not exist at last execution. In this case, new promise executed, or the promise was not executed at previous cf-agent run. - * `CHANGE` - stands for changing value or attribute such as `PromiseOutcome`, `LogMessages` or `ReleaseId` in case of new policy rollout. - * `REMOVE` - Promise was not executed last time, but it was executed previously. This is a common report for promises that have been removed from policy at some point, or they are executed only periodically (like once a hour, day etc.). - * `UNTRACKED` - CFEngine provides a mechanism for filtering unwanted data from being reported. `UNTRACKED` marker states that information is being filtered and will not report any future information about it. - -* **PolicyFile** *(text)* - Path to the file where the promise is located in. - -* **ReleaseId** *(text)* - Unique identifier of masterfiles version that is executed in the host. - -* **PromiseHash** *(text)* - Unique identifier of a promise. It is a hash of all promise attributes and their values. - -* **NameSpace** *(text)* - [Namespace][Namespaces] within which the promise is executed. If no namespace is set then it is set as: `default`. - -* **BundleName** *(text)* - [Bundle][Bundles] name where the promise is executed. - -* **PromiseType** *(text)* - [Type][Promise Types] of the promise. - -* **Promiser** *(text)* - Object affected by a promise. - -* **StackPath** *(text)* - Call stack of the promise. - -* **PromiseHandle** *(text)* - A unique id-tag string for referring promise. - -* **PromiseOutcome** *(`KEPT`/`NOTKEPT`/`REPAIRED`)* - Promise execution result. - * `KEPT` - System has been found in the state as desired by the promise. CFEngine did not have to do any action to correct the state. - * `REPAIRED` - State of the system differed from the desired state. CFEngine took successful action to correct it according to promise specification. - * `NOTKEPT` - CFEngine has failed to converge the system according to the promise specification. - -* **LogMessages** *(text[])* - List of 5 last messages generated during promise execution. If the promise is `KEPT` the messages are not reported. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. - -* **Promisees** *(text[])* - List of [promisees][Promises] defined for the promise. - -**Example query:** - -```sql -SELECT hostkey, - changetimestamp, - changeoperation, - policyfile, - releaseid, - promisehash, - namespace, - bundlename, - promisetype, - promiser, - stackpath, - promisehandle, - promiseoutcome, - logmessages, - promisees -FROM promiseexecutionslog; -``` - -**Output:** - -``` --[ RECORD 1 ]---|-------------------------------------------------- -hostkey | SHA=a4dd5... -changetimestamp | 2015-03-11 09:50:11+00 -changeoperation | ADD -policyfile | /var/cfengine/inputs/sketches/meta/api-runfile.cf -releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 -promisehash | 48bc... -namespace | default -bundlename | cfsketch_run -promisetype | methods -promiser | cfsketch_g -stackpath | /default/cfsketch_run/methods/'cfsketch_g'[0] -promisehandle | -promiseoutcome | KEPT -logmessages | {} -promisees | {} --[ RECORD 2 ]---|-------------------------------------------------- -hostkey | SHA=3b94d... -changetimestamp | 2015-03-17 08:55:38+00 -changeoperation | ADD -policyfile | /var/cfengine/inputs/inventory/any.cf -releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 -promisehash | 6eef8... -namespace | default -bundlename | inventory_autorun -promisetype | methods -promiser | disk -stackpath | /default/inventory_autorun/methods/'disk'[0] -promisehandle | cfe_internal_autorun_disk -promiseoutcome | KEPT -logmessages | {} -promisees | {} --[ RECORD 3 ]---|-------------------------------------------------- -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:43:28+00 -changeoperation | CHANGE -policyfile | /var/cfengine/inputs/inventory/any.cf -releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 -promisehash | fd6d5... -namespace | default -bundlename | inventory_autorun -promisetype | methods -promiser | mtab -stackpath | /default/inventory_autorun/methods/'mtab'[0] -promisehandle | cfe_internal_autorun_inventory_mtab -promiseoutcome | KEPT -logmessages | {} -promisees | {} -``` - - - -## Table: PromiseLog - -History of promises executed on hosts. - -**Columns:** - -* **id** *(integer)* - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ChangeTimeStamp** *(timestamp)* - The GMT time on the host when this state was first perceived. - - **Note causes of change:** - - A change in the promise signature/hash for example, altering the promise - handle, promisees, or moving the promise to a different bundle - - A change in the policy releaseId (cf_promises_release_id) - - A change in promise outcome - -* **PolicyFile** *(text)* - Path to the file where the promise is located in. - -* **ReleaseId** *(text)* - Unique identifier of masterfiles version that is executed on the host. - -* **PromiseHash** *(text)* - Unique identifier of a promise. It is a hash of all promise attributes and their values. - -* **NameSpace** *(text)* - [Namespace][Namespaces] within which the promise is executed. If no namespace is set then it is set as: `default`. - -* **BundleName** *(text)* - [Bundle][Bundles] name where the promise is executed. - -* **PromiseType** *(text)* - [Type][Promise Types] of the promise. - -* **Promiser** *(text)* - Object affected by a promise. - -* **StackPath** *(text)* - Call stack of the promise. - -* **PromiseHandle** *(text)* - A unique id-tag string for referring promise. - -* **PromiseOutcome** *(`KEPT`/`NOTKEPT`/`REPAIRED`)* - Promise execution result. - * `KEPT` - System has been found in the state as desired by the promise. CFEngine did not have to do any action to correct the state. - * `REPAIRED` - State of the system differed from the desired state. CFEngine took successful action to correct it according to promise specification. - * `NOTKEPT` - CFEngine has failed to converge the system according to the promise specification. - -* **LogMessages** *(text[])* - List of 5 last messages generated during promise execution. If the promise is `KEPT` the messages are not reported. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. - -* **Promisees** *(text[])* - List of [promisees][Promises] defined for the promise. - -**Example query:** - -```sql -SELECT hostkey, - policyfile, - releaseid, - promisehash, - namespace, - bundlename, - promisetype, - promiser, - stackpath, - promisehandle, - promiseoutcome, - logmessages, - promisees, - changetimestamp -FROM promiselog; -``` - -**Output:** - -``` --[ RECORD 1 ]---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------------------------------------------------------------------------------------------------- -hostkey | SHA=70138d580b9fd292ff856746df2fe7f9ded29db9ffca0c4d83acbbb97cde4d42 -policyfile | /var/cfengine/inputs/lib/bundles.cf -releaseid | f90866033a826aa05cf10fdc8d34a532a9cd465b -promisehash | 04659a0501f471eb1794cead6cd7a3291b78dcb195063821a7dcb4dbe7f7f804 -namespace | default -bundlename | prunedir -promisetype | files -promiser | /var/cfengine/outputs -stackpath | /default/cfe_internal_management/methods/'CFEngine_Internals'/default/cfe_internal_core_main/methods/'any'/default/cfe_internal_log_rotation/methods/'Prune old log files'/default/prunedir/files/'/var/cfengine/output -s'[1] -promisehandle | -promiseoutcome | REPAIRED -logmessages | {"Deleted file '/var/cfengine/outputs/cf_demohub_a10042_cfengine_com__1535846669_Sun_Sep__2_00_04_29_2018_0x7f4da3549700'"} -promisees | {} -changetimestamp | 2018-10-02 00:04:52+00 -``` - -## Table: Software - -Software packages installed (according to local package manager) on the hosts. -More information about CFEngine and package management can be found [here][packages]. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **SoftwareName** *(text)* - Name of installed software package. - -* **SoftwareVersion** *(text)* - Software package version. - -* **SoftwareArchitecture** *(text)* - Architecture. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp when the package was discovered / installed on the host. - -**Example query:** - -```sql -SELECT hostkey, - softwarename, - softwareversion, - softwarearchitecture, - changetimestamp -FROM software; -``` - -**Output:** - -``` --[ RECORD 1 ]--------|----------------------- -hostkey | SHA=a4dd5... -softwarename | libgssapi-krb5-2 -softwareversion | 1.12+dfsg-2ubuntu4.2 -softwarearchitecture | default -changetimestamp | 2015-03-12 10:20:18+00 --[ RECORD 2 ]--------|----------------------- -hostkey | SHA=a4dd5... -softwarename | whiptail -softwareversion | 0.52.15-2ubuntu5 -softwarearchitecture | default -changetimestamp | 2015-03-12 10:20:18+00 --[ RECORD 3 ]--------|----------------------- -hostkey | SHA=a4dd5... -softwarename | libruby1.9.1 -softwareversion | 1.9.3.484-2ubuntu1.2 -softwarearchitecture | default -changetimestamp | 2015-03-12 10:20:18+00 -``` - -## Table: SoftwareUpdates - -Patches available for installed packages on the hosts (as reported by local package manager). -The most up to date patch will be listed. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **PatchName** *(text)* - Name of the software. - -* **PatchVersion** *(text)* - Patch version. - -* **PatchArchitecture** *(text)* - Architecture of the patch. - -* **PatchReportType** *(`INSTALLED`/`AVAILABLE`)* - Patch status (`INSTALLED` status is specific only to SUSE Linux). - -* **ChangeTimeStamp** *(timestamp)* - Timestamp when the new patch / version was discovered as available on the host. - -**Example query:** - -```sql -SELECT hostkey, - patchname, - patchversion, - patcharchitecture, - patchreporttype, - changetimestamp -FROM softwareupdates; -``` - -**Output:** - -``` --[ RECORD 1 ]-----|------------------------ -hostkey | SHA=a4dd5... -patchname | libelf1 -patchversion | 0.158-0ubuntu5.2 -patcharchitecture | default -patchreporttype | AVAILABLE -changetimestamp | 2015-03-12 10:20:18+00 --[ RECORD 2 ]-----|------------------------ -hostkey | SHA=a4dd5... -patchname | libisccfg90 -patchversion | 1:9.9.5.dfsg-3ubuntu0.2 -patcharchitecture | default -patchreporttype | AVAILABLE -changetimestamp | 2015-03-12 10:20:18+00 --[ RECORD 3 ]-----|------------------------ -hostkey | SHA=a4dd5... -patchname | libc6-dev -patchversion | 2.19-0ubuntu6.6 -patcharchitecture | default -patchreporttype | AVAILABLE -changetimestamp | 2015-03-12 10:20:18+00 -``` - -## Table: SoftwareLog -Software packages installed / deleted over period of time. -More information about CFEngine and package management can be found [here][packages]. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp when the package state was discovered on the host. - **Note:** The statement if true till present time or newer entry claims otherwise. - -* **ChangeOperation** *(`ADD`,`REMOVE`)* - CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. - * `ADD` - New package have been detected / installed. Package upgrate is considered as installing a new package with a different version. - * `REMOVE` - Package have been detected to be removed / uninstalled. During upgrate older version of the package is removed and reported as so. - -* **SoftwareName** *(text)* - Name of installed software package. - -* **SoftwareVersion** *(text)* - Software package version. - -* **SoftwareArchitecture** *(text)* - Architecture. - -**Example query:** - -```sql -SELECT hostkey, - changetimestamp, - changeoperation, - softwarename, - softwareversion, - softwarearchitecture -FROM softwarelog; -``` - -**Output:** - -``` --[ RECORD 1 ]--------|----------------------- -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -softwarename | libgssapi-krb5-2 -softwareversion | 1.12+dfsg-2ubuntu4.2 -softwarearchitecture | default --[ RECORD 2 ]--------|----------------------- -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -softwarename | whiptail -softwareversion | 0.52.15-2ubuntu5 -softwarearchitecture | default --[ RECORD 3 ]--------|----------------------- -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -softwarename | libruby1.9.1 -softwareversion | 1.9.3.484-2ubuntu1.2 -softwarearchitecture | default -``` - -## Table: SoftwareUpdatesLog - -**This table was deprecated in 3.7.0. It is no longer used.** - -Patches available for installed packages on the hosts (as reported by local package manager) over period of time. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp when the patch state was discovered on the host. - **Note:** The statement if true till present time or newer entry claims otherwise. - -* **ChangeOperation** *(`ADD`,`REMOVE`)* - CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. - * `ADD` - New patch have been detected. This is a common in case of release of new patch version or new package was installed that have an upgrate available. - * `REMOVE` - Patch is not longer available. Patch may be replaced with newer version, or installed package have been upgrated. - **Note:** CFEngine reports only the most up to date version available. - -* **PatchName** *(text)* - Name of the software. - -* **PatchVersion** *(text)* - Patch version. - -* **PatchArchitecture** *(text)* - Architecture of the patch. - -* **PatchReportType** *(`INSTALLED`/`AVAILABLE`)* - Patch status (`INSTALLED` status is specific only to SUSE Linux). - -**Example query:** - -```sql -SELECT hostkey, - changetimestamp, - changeoperation, - patchname, - patchversion, - patcharchitecture, - patchreporttype -FROM softwareupdateslog; -``` - -**Output:** - -``` --[ RECORD 1 ]-----|------------------------ -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -patchname | libelf1 -patchversion | 0.158-0ubuntu5.2 -patcharchitecture | default -patchreporttype | AVAILABLE --[ RECORD 2 ]-----|------------------------ -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -patchname | libisccfg90 -patchversion | 1:9.9.5.dfsg-3ubuntu0.2 -patcharchitecture | default -patchreporttype | AVAILABLE --[ RECORD 3 ]-----|------------------------ -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -patchname | libc6-dev -patchversion | 2.19-0ubuntu6.6 -patcharchitecture | default -patchreporttype | AVAILABLE -``` - -## Table: Status - -Statuses of report collection. cf-hub records all collection attempts and whether they are FAILEDC or CONSUMED. CONSUMED means next one will be delta. FAILEDC means next one will be REBASE. - -**Columns:** - -* **host** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ts** *(timestamp)* - Timestamp of last data provided by client during report collection. This is used by delta queries to request a start time. - -* **status** *(`FAILEDC`,`CONSUMED`)* - CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. - * `FAILEDC` - New patch have been detected. This is a common in case of release of new patch version or new package was installed that have an upgrate available. - * `CONSUMED` - Patch is not longer available. Patch may be replaced with newer version, or installed package have been upgrated. - **Note:** CFEngine reports only the most up to date version available. - -* **lstatus** *(text)* - Deprecated - -* **type** *(text)* - Deprecated - -* **who** *(integer)* - Deprecated - -* **whr** *integer* - Deprecated - -**Example query:** - -```sql -SELECT hostkey, - changetimestamp, - changeoperation, - patchname, - patchversion, - patcharchitecture, - patchreporttype -FROM softwareupdateslog; -``` - -**Output:** - -``` --[ RECORD 1 ]-----|------------------------ -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -patchname | libelf1 -patchversion | 0.158-0ubuntu5.2 -patcharchitecture | default -patchreporttype | AVAILABLE --[ RECORD 2 ]-----|------------------------ -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -patchname | libisccfg90 -patchversion | 1:9.9.5.dfsg-3ubuntu0.2 -patcharchitecture | default -patchreporttype | AVAILABLE --[ RECORD 3 ]-----|------------------------ -hostkey | SHA=3b94d... -changetimestamp | 2015-03-10 13:38:14+00 -changeoperation | ADD -patchname | libc6-dev -patchversion | 2.19-0ubuntu6.6 -patcharchitecture | default -patchreporttype | AVAILABLE -``` - - -## Table: Variables - -Variables and their values set on hosts at their last reported cf-agent execution. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **NameSpace** *(text)* - [Namespace][Namespaces] within which the variable is set. If no namespace is set then it is set as: `default`. - -* **Bundle** *(text)* - [Bundle][Bundles] name where the variable is set. - -* **VariableName** *(text)* - Name of the variable. - -* **VariableValue** *(text)* - Variable value serialized to string. - * List types such as: `slist`, `ilist`, `rlist` are serialized with CFEngine list format: {'value','value'}. - * `Data` type is serialized as JSON string. - -* **VariableType** *(text)* - Type of the variable. [List][Variables] of supported variable types. - -* **MetaTags** *(text[])* - List of [meta tags][Tags for variables, classes, and bundles] set for the variable. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp since when variable is set in its current form. - **Note:** If any of variable attributes change such as its `VariableValue` or `Bundle`, the timestamp will be updated. - -**Example query:** - -```sql -SELECT hostkey, - namespace, - bundle, - variablename, - variablevalue, - variabletype, - metatags, - changetimestamp -FROM variables; -``` - -**Output:** - -``` --[ RECORD 1 ]---|------------------------------------------------------------- -hostkey | SHA=a4dd5... -namespace | default -bundle | cfe_autorun_inventory_memory -variablename | total -variablevalue | 490.00 -variabletype | string -metatags | {source=promise,inventory,"attribute_name=Memory size (MB)"} -changetimestamp | 2015-03-11 09:51:41+00 --[ RECORD 2 ]---|------------------------------------------------------------- -hostkey | SHA=a4dd5... -namespace | default -bundle | cfe_autorun_inventory_listening_ports -variablename | ports -variablevalue | {'22','111','5308','38854','50241'} -variabletype | slist -metatags | {source=promise,inventory,"attribute_name=Ports listening"} -changetimestamp | 2015-03-11 09:51:41+00 --[ RECORD 3 ]---|------------------------------------------------------------- -hostkey | SHA=a4dd5... -namespace | default -bundle | cfe_autorun_inventory_memory -variablename | free -variablevalue | 69.66 -variabletype | string -metatags | {source=promise,report} -changetimestamp | 2015-03-11 14:27:12+00 -``` - -## Table: Variables_dictionary - -Inventory attributes, these data are using in [List of inventory attributes API][Inventory API#List of inventory attributes] - -**Columns:** - -* **Id** *(integer)* - Auto incremental ID -* **Attribute_name** *(text)* - Attribute name -* **Category** *(text)* *(`Hardware`,`Software`,`Network`, `Security`, `User defined`)* - Attribute category -* **Readonly** *(integer)* *(`0`,`1`)* - Is attribute readonly -* **Type** *(text)* - Type of the attribute. [List][Variables] of supported variable types. -* **convert_function** *(text)* - Convert function. Emp.: `cf_clearSlist` - to transform string like `{"1", "2"}` to `1, 2` -* **keyname** *(text)* - Key name -* **Enabled** *(integer)* *(`0`,`1`)* - Is attribute enabled for the API - -**Example query:** - -```sql -SELECT attribute_name, - category, - readonly, - type, - convert_function, - enabled -FROM variables_dictionary; -``` - -**Output:** - -``` --[ RECORD 1 ]---|----------------------------------------------------- -attribute_name | Architecture -category | Software -readonly | 1 -type | string -convert_function| -enabled | 1 --[ RECORD 2 ]---|----------------------------------------------------- -attribute_name | IPv4 addresses -category | Network -readonly | 1 -type | slist -convert_function| cf_clearSlist -enabled | 1 -``` - -## Table: VariablesLog - -CFEngine variables set on hosts by CFEngine over period of time. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. - -* **ChangeTimeStamp** *(timestamp)* - Timestamp since when variable is set in its current form. - **Note:** The statement if true till present time or newer entry claims otherwise. - -* **ChangeOperation** *(`ADD`,`CHANGE`,`REMOVE`,`UNTRACKED`)* - CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. - * `ADD` - stands for introducing a new entry which did not exist before. In this case, new CFEngine variable have been introduced. - * `CHANGE` - stands for changing value or attribute such as `VariableValue` or `MetaTags` have changed. - * `REMOVE` - Variable have not been set. - * `UNTRACKED` - CFEngine provides a mechanism for filtering unwanted data from being reported. `UNTRACKED` marker states that information is being filtered and will not report any future information about it. - -* **NameSpace** *(text)* - [Namespace][Namespaces] within which the variable is set. If no namespace is set then it is set as: `default`. - -* **Bundle** *(text)* - [Bundle][Bundles] name where the variable is set. - -* **VariableName** *(text)* - Name of the variable. - -* **VariableValue** *(text)* - Variable value serialized to string. - * List types such as: `slist`, `ilist`, `rlist` are serialized with CFEngine list format: {'value','value'}. - * `Data` type is serialized as JSON string. - -* **VariableType** *(text)* - Type of the variable. [List][Variables] of supported variable types. - -* **MetaTags** *(text[])* - List of [meta tags][Tags for variables, classes, and bundles] set for the variable. - -**Example query:** - -```sql -SELECT hostkey, - changetimestamp, - changeoperation, - namespace, - bundle, - variablename, - variablevalue, - variabletype, - metatags -FROM variableslog; -``` - -**Output:** - -``` --[ RECORD 1 ]---|----------------------------------------------------- -hostkey | SHA=2aab8... -changetimestamp | 2015-03-10 13:43:00+00 -changeoperation | CHANGE -namespace | default -bundle | mon -variablename | av_cpu -variablevalue | 0.06 -variabletype | string -metatags | {monitoring,source=environment} --[ RECORD 2 ]---|----------------------------------------------------- -hostkey | SHA=2aab8... -changetimestamp | 2015-03-10 13:40:20+00 -changeoperation | ADD -namespace | default -bundle | sys -variablename | arch -variablevalue | x86_64 -variabletype | string -metatags | {inventory,source=agent,attribute_name=Architecture} --[ RECORD 3 ]---|----------------------------------------------------- -hostkey | SHA=2aab8... -changetimestamp | 2015-03-10 13:43:00+00 -changeoperation | CHANGE -namespace | default -bundle | mon -variablename | av_diskfree -variablevalue | 67.01 -variabletype | string -metatags | {monitoring,source=environment} -``` -## Table: v_hosts - -V_hosts table contains information about hosts. - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect - data concerning same hosts. - -* **iscallcollected** *(boolean)* - Is host call collected - -* **LastReportTimeStamp** *(timestamp)* - Timestamp of the most recent successful report collection. - -* **FirstReportTimeStamp** *(timestamp)* - Timestamp when the host reported to the hub for the first time, which - indicate when the host was bootstrapped to the hub. - -**Example query:** - -```sql -SELECT hostkey, - iscallcollected, - lastreporttimestamp, - firstreporttimestamp -FROM hosts; -``` - -**Output:** - -``` --[ RECORD 1 ]--------|----------------------- -hostkey | SHA=a4dd... -iscallcollected | t -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 --[ RECORD 2 ]--------|----------------------- -hostkey | SHA=3b94... -iscallcollected | f -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:34:20+00 --[ RECORD 3 ]--------|----------------------- -hostkey | SHA=2aab... -iscallcollected | f -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 -``` - -## Table: vm_hosts - -vm_hosts table contains basic information about hosts managed by CFEngine. -In this table data are cached what gives a better query performance - -**Columns:** - -* **HostKey** *(text)* - Unique host identifier. All tables can be joined by `HostKey` to connect - data concerning same hosts. - -* **HostName** *(text)* - Host name locally detected on the host, configurable as `hostIdentifier` - option in [Settings API][Status and Settings REST API#Get settings] and - Mission Portal settings UI. - -* **IPAddress** *(text)* - IP address of the host derived from the lastseen database (this is expected - to be the IP address from which connections come from, beware NAT will cause - multiple hosts to appear to have the same IP address). - -* **LastReportTimeStamp** *(timestamp)* - Timestamp of the most recent successful report collection. - -* **FirstReportTimeStamp** *(timestamp)* - Timestamp when the host reported to the hub for the first time, which - indicate when the host was bootstrapped to the hub. - -**Example query:** - -```sql -SELECT hostkey, - hostname, - ipaddress, - lastreporttimestamp, - firstreporttimestamp -FROM hosts; -``` - -**Output:** - -``` --[ RECORD 1 ]--------|----------------------- -hostkey | SHA=a4dd... -hostname | host001 -ipaddress | 192.168.56.151 -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 --[ RECORD 2 ]--------|----------------------- -hostkey | SHA=3b94... -hostname | hub -ipaddress | 192.168.56.65 -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:34:20+00 --[ RECORD 3 ]--------|----------------------- -hostkey | SHA=2aab... -hostname | host002 -ipaddress | 192.168.56.152 -lastreporttimestamp | 2015-03-10 14:20:20+00 -firstreporttimestamp | 2015-03-10 13:40:20+00 -``` +- `cfdb` - Database containing information that hosts report. +- `cfsettings` - Database containing settings used by Mission Portal APIs, no reported data. +- `cfmp` - Database containing Mission Portal related settings not processed by API. diff --git a/api/enterprise-api-ref/sql-schema/cfdb.markdown b/api/enterprise-api-ref/sql-schema/cfdb.markdown new file mode 100644 index 000000000..f44820f69 --- /dev/null +++ b/api/enterprise-api-ref/sql-schema/cfdb.markdown @@ -0,0 +1,1781 @@ +--- +layout: default +title: cfdb +published: true +--- + +CFEngine allows standardized SQL `SELECT` queries to be used with [REST API][Query REST API#Execute SQL query]. +Queries can be used with following database schema. + +```bash +curl -k --user admin:admin https://hub.cfengine.com/api/query -X POST -d "{ \"query\": \"SELECT Hosts.HostName, Hosts.IPAddress FROM Hosts WHERE hostname = 'hub'\"}" +``` + +## Table: AgentStatus + +Agent status contains information about last cf-agent execution. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **AgentExecutionInterval** *(integer)* + Estimated interval in which cf-agent is being executed, as cf-agent execution interval is expressed in CFEngine context expressions (Min00_05 etc.) it can be not regular, this interval is discovered by analyzing last few cf-agent execution timestamps. Expressed in seconds. + +* **LastAgentLocalExecutionTimeStamp** *(timestamp)* + Timestamp of last cf-agent execution on the host. + +* **LastAgentExecutionStatus** *(`OK`/`FAIL`)* + cf-agent execution status. In case cf-agent will not execute within 3x `AgentExecutionInterval` from last execution, status will be set to `FAIL`. Failure may indicate cf-execd issues, or cf-agent crashes. + +**Example query:** + +```sql +SELECT hostkey, + agentexecutioninterval, + lastagentlocalexecutiontimestamp, + lastagentexecutionstatus +FROM agentstatus; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------------------|----------------------- +hostkey | SHA=3b94d... +agentexecutioninterval | 277 +lastagentlocalexecutiontimestamp | 2015-03-11 12:37:39+00 +lastagentexecutionstatus | OK +-[ RECORD 2 ]--------------------|----------------------- +hostkey | SHA=a4dd5... +agentexecutioninterval | 275 +lastagentlocalexecutiontimestamp | 2015-03-11 12:36:36+00 +lastagentexecutionstatus | OK +-[ RECORD 3 ]--------------------|----------------------- +hostkey | SHA=2aab8... +agentexecutioninterval | 284 +lastagentlocalexecutiontimestamp | 2015-03-11 12:36:51+00 +lastagentexecutionstatus | OK +``` + +## Table: BenchmarksLog + +Data from internal cf-agent monitoring as also [measurements promises][measurements]. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **EventName** *(text)* + Name of measured event. + +* **StandardDeviation** *(numeric)* + Dispersion of a set of data from its mean. + +* **AverageValue** *(numeric)* + Average value. + +* **LastValue** *(numeric)* + Last measured value. + +* **CheckTimeStamp** *(timestamp)* + Measurement time. + +**Example query:** + +```sql +SELECT hostkey, + eventname, + standarddeviation, + averagevalue, + lastvalue, + checktimestamp +FROM benchmarkslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]-----|-------------------------------------------------------- +hostkey | SHA=3b94d... +eventname | CFEngine Execution ('/var/cfengine/inputs/promises.cf') +standarddeviation | 7.659365 +averagevalue | 3.569665 +lastvalue | 1.170841 +checktimestamp | 2015-03-10 14:08:12+00 +-[ RECORD 2 ]---=-|-------------------------------------------------------- +hostkey | SHA=3b94d... +eventname | CFEngine Execution ('/var/cfengine/inputs/update.cf') +standarddeviation | 0.131094 +averagevalue | 0.422757 +lastvalue | 0.370686 +checktimestamp | 2015-03-10 14:08:11+00 +-[ RECORD 3 ]-----|-------------------------------------------------------- +hostkey | SHA=3b94d... +eventname | DBReportCollectAll +standarddeviation | 0.041025 +averagevalue | 1.001964 +lastvalue | 1.002346 +checktimestamp | 2015-03-10 14:05:20+00 +``` + +## Table: Contexts + +CFEngine contexts present on hosts at their last reported cf-agent execution. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ContextName** *(text)* + CFEngine [context][Classes and decisions] set by cf-agent. + +* **MetaTags** *(text[])* + List of [meta tags][Tags for variables, classes, and bundles] set for the context. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp since when context is set in its current form. + **Note:** If any of the context attributes change, the timestamp will be updated. + +**Example query:** + +```sql +SELECT hostkey, + contextname, + metatags, + changetimestamp +FROM contexts; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|------------------------------------------------------- +hostkey | SHA=a4dd5... +contextname | enterprise_3_6_5 +metatags | {inventory,attribute_name=none,source=agent,hardclass} +changetimestamp | 2015-03-11 09:50:11+00 +-[ RECORD 2 ]---|------------------------------------------------------- +hostkey | SHA=a4dd5... +contextname | production +metatags | {report,"Production environment"} +changetimestamp | 2015-03-11 09:50:11+00 +-[ RECORD 3 ]---|------------------------------------------------------- +hostkey | SHA=a4dd5... +contextname | enterprise_edition +metatags | {inventory,attribute_name=none,source=agent,hardclass} +changetimestamp | 2015-03-11 09:50:11+00 +``` + +## Table: ContextsLog + +CFEngine contexts set on hosts by CFEngine over period of time. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp since when context is set in its current form. + **Note:** The statement if true till present time or newer entry claims otherwise. + +* **ChangeOperation** *(`ADD`,`CHANGE`,`REMOVE`,`UNTRACKED`)* + CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. + * `ADD` - stands for introducing a new entry which did not exist before. In this case, new CFEngine context have been introduced. + * `CHANGE` - stands for changing value or attribute such as `MetaTags` have changed. + * `REMOVE` - Context have not been set. + * `UNTRACKED` - CFEngine provides a mechanism for filtering unwanted data from being reported. `UNTRACKED` marker states that information about this context is being filtered and will not report any future information about it. + +* **ContextName** *(text)* + CFEngine [context][Classes and decisions] set by cf-agent. + +* **MetaTags** *(text[])* + List of [meta tags][Tags for variables, classes, and bundles] set for the context. + + +**Example query:** + +```sql +SELECT hostkey, + changetimestamp, + changeoperation, + contextname, + metatags +FROM contextslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|------------------------------------------------------- +hostkey | SHA=a4dd5... +changetimestamp | 2015-03-10 13:40:20+00 +changeoperation | ADD +contextname | debian +metatags | {inventory,attribute_name=none,source=agent,hardclass} +-[ RECORD 2 ]---|------------------------------------------------------- +hostkey | SHA=a4dd5... +changetimestamp | 2015-03-10 14:40:20+00 +changeoperation | ADD +contextname | ipv4_192_168 +metatags | {inventory,attribute_name=none,source=agent,hardclass} +-[ RECORD 3 ]---|------------------------------------------------------- +hostkey | SHA=a4dd5... +changetimestamp | 2015-03-10 15:40:20+00 +changeoperation | ADD +contextname | nova_3_6_5 +metatags | {inventory,attribute_name=none,source=agent,hardclass} +``` + +## Table: FileChangesLog + +Log of changes detected to files that are set to be [monitored][files#changes] by cf-agent. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **PromiseHandle** *(text)* + A Uniqueue id-tag string for referring promise. + +* **FileName** *(text)* + Name of the file that have changed. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp when CFEngine have detected the change to the file. + +* **ChangeType** *(text)* + Type of change detected on the monitored file. + * DIFF - change in content (with file diff) + * S - change in file stats + * C - change in content (based on file hash) + +* **ChangeDetails** *(text[])* + Information about changes detected to the file. Such as file stats information, file diff etc. + +**Example query:** + +```sql +SELECT hostkey, + promisehandle, + filename, + changetimestamp, + changetype, + changedetails +FROM filechangeslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|------------------------------------------------------------ +hostkey | SHA=3b94d... +promisehandle | my_test_promise +filename | /tmp/app.conf +changetimestamp | 2015-03-13 13:16:10+00 +changetype | C +changedetails | {"Content changed"} +-[ RECORD 2 ]---|------------------------------------------------------------ +hostkey | SHA=3b94d... +promisehandle | my_test_promise +filename | /tmp/app.conf +changetimestamp | 2015-03-13 13:16:10+00 +changetype | DIFF +changedetails | {"-,1,loglevel = info","+,1,loglevel = debug"} +-[ RECORD 3 ]---|------------------------------------------------------------ +hostkey | SHA=3b94d... +promisehandle | my_test_promise +filename | /tmp/app.conf +changetimestamp | 2015-03-09 11:46:36+00 +changetype | S +changedetails | {"Modified time: Mon Mar 9 11:37:50 -> Mon Mar 9 11:42:27"} +``` + +## Table: Hosts + +Hosts table contains basic information about hosts managed by CFEngine. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect + data concerning same hosts. + +* **HostName** *(text)* + Host name locally detected on the host, configurable as `hostIdentifier` + option in [Settings API][Status and settings REST API#Get settings] and + Mission Portal settings UI. + +* **IPAddress** *(text)* + IP address of the host derived from the lastseen database (this is expected + to be the IP address from which connections come from, beware NAT will cause + multiple hosts to appear to have the same IP address). + +* **LastReportTimeStamp** *(timestamp)* + Timestamp of the most recent successful report collection. + +* **FirstReportTimeStamp** *(timestamp)* + Timestamp when the host reported to the hub for the first time, which + indicate when the host was bootstrapped to the hub. + +**Example query:** + +```sql +SELECT hostkey, + hostname, + ipaddress, + lastreporttimestamp, + firstreporttimestamp +FROM hosts; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------|----------------------- +hostkey | SHA=a4dd... +hostname | host001 +ipaddress | 192.168.56.151 +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +-[ RECORD 2 ]--------|----------------------- +hostkey | SHA=3b94... +hostname | hub +ipaddress | 192.168.56.65 +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:34:20+00 +-[ RECORD 3 ]--------|----------------------- +hostkey | SHA=2aab... +hostname | host002 +ipaddress | 192.168.56.152 +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +``` + +## Table: Hosts_not_reported + +Hosts_not_reported table contains information about not reported hosts. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect + data concerning same hosts. + +* **iscallcollected** *(boolean)* + Is host call collected + +* **LastReportTimeStamp** *(timestamp)* + Timestamp of the most recent successful report collection. + +* **FirstReportTimeStamp** *(timestamp)* + Timestamp when the host reported to the hub for the first time, which + indicate when the host was bootstrapped to the hub. + +**Example query:** + +```sql +SELECT hostkey, + iscallcollected, + lastreporttimestamp, + firstreporttimestamp +FROM hosts; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------|----------------------- +hostkey | SHA=a4dd... +iscallcollected | t +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +-[ RECORD 2 ]--------|----------------------- +hostkey | SHA=3b94... +iscallcollected | f +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:34:20+00 +-[ RECORD 3 ]--------|----------------------- +hostkey | SHA=2aab... +iscallcollected | f +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +``` + +## Table: HubConnectionErrors + +Networking errors encountered by cf-hub during its operation. + +**Columns:** + +* **HostKey** *(text)* + Unique identifier of the host that cf-hub was connecting to. + +* **CheckTimeStamp** *(timestamp)* + Timestamp when the error occurred. + +* **Message** *(text)* + Error type / message. + +* **QueryType** *(text)* + Type of query that was intended to be sent by hub during failed connection attempt. + +**Example query:** + +```sql +SELECT hostkey, + checktimestamp, + message, + querytype, +FROM hubconnectionErrors; +``` + +**Output:** + +``` +-[ RECORD 1 ]--|-------------------------- +hostkey | SHA=3b94d... +checktimestamp | 2015-03-13 13:16:10+00 +message | ServerNoReply +querytype | delta +-[ RECORD 2 ]--|-------------------------- +hostkey | SHA=3b94d... +checktimestamp | 2015-03-13 14:16:10+00 +message | InvalidData +querytype | rebase +-[ RECORD 3 ]--|-------------------------- +hostkey | SHA=3b94d... +checktimestamp | 2015-03-13 15:16:10+00 +message | ServerAuthenticationError +querytype | delta +``` + +## Table: Inventory + +Inventory data + +**Columns:** + +* **HostKey** *(text)* + Unique identifier of the host. + +* **keyname** *(text)* + Name of the key. + +* **type** *(text)* + Type of the variable. [List][Variables] of supported variable types. + +* **metatags** *(text[])* + List of [meta tags][Tags for variables, classes, and bundles] set for the variable. + +* **value** *(text)* + Variable value serialized to string. + * List types such as: `slist`, `ilist`, `rlist` are serialized with CFEngine list format: {'value','value'}. + * `Data` type is serialized as JSON string. + +**Example query:** + +```sql +SELECT hostkey, + keyname, + type, + metatags, + value +FROM Inventory; +``` + +**Output:** + +``` +-[ RECORD 1 ]--|-------------------------- +hostkey | SHA=3b94d... +keyname | default.sys.fqhost +type | string +metatags | {inventory,source=agent,"attribute_name=Host name"} +value | host name +-[ RECORD 2 ]--|-------------------------- +hostkey | SHA=3b94d... +keyname | default.sys.uptime +type | int +metatags | {inventory,source=agent,"attribute_name=Uptime minutes"} +value | 4543 +``` + +## Table: Inventory_new + +Inventory data grouped by host + +**Columns:** + +* **HostKey** *(text)* + Unique identifier of the host. + +* **values** *(jsonb)* + Inventory values presented in JSON format + + +**Example query:** + +```sql +SELECT hostkey, + values +FROM Inventory_new; +``` + +**Output:** + +``` +-[ RECORD 1 ]--|-------------------------- +hostkey | SHA=3b94d... +values | {"OS": "ubuntu", "OS type": "linux", "CPU model": "CPU model A10", "Host name": "SHA=aa11bb1", "OS kernel": "14.4.0-53-generic", "Interfaces": "pop, imap", "BIOS vendor": "BIOS vendor", "CFEngine ID": "SHA=aa11bb1", "CPU sockets": "229", "New OS type": "linux", "Architecture": "x86_64"} +-[ RECORD 2 ]--|-------------------------- +hostkey | SHA=5rt43... +values | {"OS": "ubuntu", "OS type": "linux", "CPU model": "CPU model A10", "Host name": "SHA=aa11bb1", "OS kernel": "14.4.0-53-generic", "Interfaces": "pop, imap", "BIOS vendor": "BIOS vendor", "CFEngine ID": "SHA=aa11bb1", "CPU sockets": "229", "New OS type": "linux", "Architecture": "x86_64"} +``` + +## Table: LastSeenHosts + +Information about communication between CFEngine clients. Effectively a snapshot +of each hosts lastseen database (`cf_lastseen.lmdb`, `cf-key -s`) at the time of +their last reported `cf-agent` execution. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **LastSeenDirection** *(`INCOMING`/`OUTGOING`)* + Direction within which the connection was established. + * `INCOMING` - host received incoming connection. + * `OUTGOING` - host opened connection to remote host. + +* **RemoteHostKey** *(text)* + `HostKey` of the remote host. + +* **RemoteHostIP** *(text)* + IP address of the remote host. + +* **LastSeenTimeStamp** *(timestamp)* + Time when the connection was established. + +* **LastSeenInterval** *(real)* + Average time period (seconds) between connections for the given `LastSeenDirection` with the host. + +**Example query:** + +```sql +SELECT hostkey, + lastseendirection, + remotehostkey, + remotehostip, + lastseentimestamp, + lastseeninterval +FROM lastseenhosts; +``` + +**Output:** + +``` +-[ RECORD 1 ]-----|----------------------- +hostkey | SHA=3b94d... +lastseendirection | OUTGOING +remotehostkey | SHA=2aab8... +remotehostip | 192.168.56.152 +lastseentimestamp | 2015-03-13 12:20:45+00 +lastseeninterval | 299 +-[ RECORD 2 ]-----|------------------------ +hostkey | SHA=3b94d... +lastseendirection | INCOMING +remotehostkey | SHA=a4dd5... +remotehostip | 192.168.56.151 +lastseentimestamp | 2015-03-13 12:22:06+00 +lastseeninterval | 298 +-[ RECORD 3 ]-----|------------------------ +hostkey | SHA=2aab8... +lastseendirection | INCOMING +remotehostkey | SHA=3b94d... +remotehostip | 192.168.56.65 +lastseentimestamp | 2015-03-13 12:20:45+00 +lastseeninterval | 299 +``` + +## Table: LastSeenHostsLogs + +History of LastSeenHosts table + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **LastSeenDirection** *(`INCOMING`/`OUTGOING`)* + Direction within which the connection was established. + * `INCOMING` - host received incoming connection. + * `OUTGOING` - host opened connection to remote host. + +* **RemoteHostKey** *(text)* + `HostKey` of the remote host. + +* **RemoteHostIP** *(text)* + IP address of the remote host. + +* **LastSeenTimeStamp** *(timestamp)* + Time when the connection was established. + +* **LastSeenInterval** *(real)* + Average time period (seconds) between connections for the given `LastSeenDirection` with the host. + +**Example query:** + +```sql +SELECT hostkey, + lastseendirection, + remotehostkey, + remotehostip, + lastseentimestamp, + lastseeninterval +FROM LastSeenHostsLogs; +``` + +**Output:** + +``` +-[ RECORD 1 ]-----|----------------------- +hostkey | SHA=3b94d... +lastseendirection | OUTGOING +remotehostkey | SHA=2aab8... +remotehostip | 192.168.56.152 +lastseentimestamp | 2015-03-13 12:20:45+00 +lastseeninterval | 299 +-[ RECORD 2 ]-----|------------------------ +hostkey | SHA=3b94d... +lastseendirection | INCOMING +remotehostkey | SHA=a4dd5... +remotehostip | 192.168.56.151 +lastseentimestamp | 2015-03-13 12:22:06+00 +lastseeninterval | 298 +-[ RECORD 3 ]-----|------------------------ +hostkey | SHA=2aab8... +lastseendirection | INCOMING +remotehostkey | SHA=3b94d... +remotehostip | 192.168.56.65 +lastseentimestamp | 2015-03-13 12:20:45+00 +lastseeninterval | 299 +``` + +## Table: MonitoringHg + +Stores 1 record for each observable per host. + +**Columns:** + +* **host** *(text)* + Unique host identifier. Referred to in other tables as `HostKey` to connect + data concerning same hosts. + +* **id** *(text)* + Name of monitored metric. The handle of the measurement promise. + +* **ar1** *(real)* + Average across 66 observations. + +## Table: MonitoringMgMeta + +Stores 1 record for each observable per host. + +**Columns:** + +* **id** *(integer)* + Unique identifier for host observable. + +* **hostkey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect + data concerning same hosts. + +* **observable** *(text)* + Name of monitored metric. The handle of the measurement promise. + +* **global** *(boolean)* + +* **expected_min** *(real)* + Minimum expected value. + +* **expected_max** *(real)* + Maximum expected value. + +* **unit** *(text)* + Unit of measurement. + +* **description** *(text)* + Description of unit of measurement. + +* **updatedtimestamp** *(timestamp with time zone)* + Time when measurement sampled. + +* **lastupdatedsample** *(integer)* + Value of most recently collected measurement. + +## Table: MonitoringYrMeta + +Stores 1 record for each observable per host. + +**Columns:** + +* **id** *(integer)* + Unique identifier for host observable. + +* **hostkey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect + data concerning same hosts. + +* **observable** *(text)* + Name of monitored metric. The handle of the measurement promise. + +* **global** *(boolean)* + +* **expected_min** *(real)* + Minimum expected value. + +* **expected_max** *(real)* + Maximum expected value. + +* **unit** *(text)* + Unit of measurement. + +* **description** *(text)* + Description of unit of measurement. + +* **lastupdatedsample** *(integer)* + Value of most recently collected measurement. + +## Table: PromiseExecutions + +Promises executed on hosts during their last reported cf-agent run. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **PolicyFile** *(text)* + Path to the file where the promise is located in. + +* **ReleaseId** *(text)* + Unique identifier of masterfiles version that is executed on the host. + +* **PromiseHash** *(text)* + Unique identifier of a promise. It is a hash of all promise attributes and their values. + +* **NameSpace** *(text)* + [Namespace][Namespaces] within which the promise is executed. If no namespace is set then it is set as: `default`. + +* **BundleName** *(text)* + [Bundle][Bundles] name where the promise is executed. + +* **PromiseType** *(text)* + [Type][Promise types] of the promise. + +* **Promiser** *(text)* + Object affected by a promise. + +* **StackPath** *(text)* + Call stack of the promise. + +* **PromiseHandle** *(text)* + A unique id-tag string for referring promise. + +* **PromiseOutcome** *(`KEPT`/`NOTKEPT`/`REPAIRED`)* + Promise execution result. + * `KEPT` - System has been found in the state as desired by the promise. CFEngine did not have to do any action to correct the state. + * `REPAIRED` - State of the system differed from the desired state. CFEngine took successful action to correct it according to promise specification. + * `NOTKEPT` - CFEngine has failed to converge the system according to the promise specification. + +* **LogMessages** *(text[])* + List of 5 last messages generated during promise execution. If the promise is `KEPT` the messages are not reported. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. + +* **Promisees** *(text[])* + List of [promisees][Promises] defined for the promise. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp since when the promise is continuously executed by cf-agent in its current configuration and provides the same output. + **Note:** If any of the promise dynamic attributes change, like promise outcome, log messages or the new policy version will be rolled out. This timestamp will be changed. + +**Example query:** + +```sql +SELECT hostkey, + policyfile, + releaseid, + promisehash, + namespace, + bundlename, + promisetype, + promiser, + stackpath, + promisehandle, + promiseoutcome, + logmessages, + promisees, + changetimestamp +FROM softwareupdates; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|--------------------------------------------------------- +hostkey | SHA=a4dd5... +policyfile | /var/cfengine/inputs/inventory/any.cf +releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 +promisehash | fd6d5e40b734e35d9e8b2ed071dfe390f23148053adaae3dbb936... +namespace | default +bundlename | inventory_autorun +promisetype | methods +promiser | mtab +stackpath | /default/inventory_autorun/methods/'mtab'[0] +promisehandle | cfe_internal_autorun_inventory_mtab +promiseoutcome | KEPT +logmessages | {} +promisees | {} +changetimestamp | 2015-03-12 10:20:18+00 +-[ RECORD 2 ]---|--------------------------------------------------------- +hostkey | SHA=a4dd5... +policyfile | /var/cfengine/inputs/promises.cf +releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 +promisehash | 925b04453ef86ff2e43228a5ca5d56dc4d69ddf12378d6fdba28b... +namespace | default +bundlename | service_catalogue +promisetype | methods +promiser | security +stackpath | /default/service_catalogue/methods/'security'[0] +promisehandle | service_catalogue_change_management +promiseoutcome | KEPT +logmessages | {} +promisees | {goal_infosec,goal_compliance} +changetimestamp | 2015-03-12 10:20:18+00 +-[ RECORD 3 ]---|--------------------------------------------------------- +hostkey | SHA=3b94d... +policyfile | /var/cfengine/inputs/lib/3.6/bundles.cf +releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 +promisehash | 47f64d43f21bc6162b4f21bf385e715535617eebc649b259ebaca... +namespace | default +bundlename | logrotate +promisetype | files +promiser | /var/cfengine/cf3.hub.runlog +stackpath | /default/cfe_internal_management/files/'any'/default/... +promisehandle | +promiseoutcome | REPAIRED +logmessages | {"Rotating files '/var/cfengine/cf3.hub.runlog'"} +promisees | {} +changetimestamp | 2015-03-12 14:52:36+00 +``` + +## Table: PromiseExecutionsLog + +**This table was deprecated in 3.7.0. It is no longer used.** + +Promise status / outcome changes over period of time. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp when the promise state or outcome changed. + **Note:** The statement if true till present time or newer entry claims otherwise. + +* **ChangeOperation** *(`ADD`,`CHANGE`,`REMOVE`,`UNTRACKED`)* + CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. + * `ADD` - stands for introducing a new entry which did not exist at last execution. In this case, new promise executed, or the promise was not executed at previous cf-agent run. + * `CHANGE` - stands for changing value or attribute such as `PromiseOutcome`, `LogMessages` or `ReleaseId` in case of new policy rollout. + * `REMOVE` - Promise was not executed last time, but it was executed previously. This is a common report for promises that have been removed from policy at some point, or they are executed only periodically (like once a hour, day etc.). + * `UNTRACKED` - CFEngine provides a mechanism for filtering unwanted data from being reported. `UNTRACKED` marker states that information is being filtered and will not report any future information about it. + +* **PolicyFile** *(text)* + Path to the file where the promise is located in. + +* **ReleaseId** *(text)* + Unique identifier of masterfiles version that is executed in the host. + +* **PromiseHash** *(text)* + Unique identifier of a promise. It is a hash of all promise attributes and their values. + +* **NameSpace** *(text)* + [Namespace][Namespaces] within which the promise is executed. If no namespace is set then it is set as: `default`. + +* **BundleName** *(text)* + [Bundle][Bundles] name where the promise is executed. + +* **PromiseType** *(text)* + [Type][Promise types] of the promise. + +* **Promiser** *(text)* + Object affected by a promise. + +* **StackPath** *(text)* + Call stack of the promise. + +* **PromiseHandle** *(text)* + A unique id-tag string for referring promise. + +* **PromiseOutcome** *(`KEPT`/`NOTKEPT`/`REPAIRED`)* + Promise execution result. + * `KEPT` - System has been found in the state as desired by the promise. CFEngine did not have to do any action to correct the state. + * `REPAIRED` - State of the system differed from the desired state. CFEngine took successful action to correct it according to promise specification. + * `NOTKEPT` - CFEngine has failed to converge the system according to the promise specification. + +* **LogMessages** *(text[])* + List of 5 last messages generated during promise execution. If the promise is `KEPT` the messages are not reported. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. + +* **Promisees** *(text[])* + List of [promisees][Promises] defined for the promise. + +**Example query:** + +```sql +SELECT hostkey, + changetimestamp, + changeoperation, + policyfile, + releaseid, + promisehash, + namespace, + bundlename, + promisetype, + promiser, + stackpath, + promisehandle, + promiseoutcome, + logmessages, + promisees +FROM promiseexecutionslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|-------------------------------------------------- +hostkey | SHA=a4dd5... +changetimestamp | 2015-03-11 09:50:11+00 +changeoperation | ADD +policyfile | /var/cfengine/inputs/sketches/meta/api-runfile.cf +releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 +promisehash | 48bc... +namespace | default +bundlename | cfsketch_run +promisetype | methods +promiser | cfsketch_g +stackpath | /default/cfsketch_run/methods/'cfsketch_g'[0] +promisehandle | +promiseoutcome | KEPT +logmessages | {} +promisees | {} +-[ RECORD 2 ]---|-------------------------------------------------- +hostkey | SHA=3b94d... +changetimestamp | 2015-03-17 08:55:38+00 +changeoperation | ADD +policyfile | /var/cfengine/inputs/inventory/any.cf +releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 +promisehash | 6eef8... +namespace | default +bundlename | inventory_autorun +promisetype | methods +promiser | disk +stackpath | /default/inventory_autorun/methods/'disk'[0] +promisehandle | cfe_internal_autorun_disk +promiseoutcome | KEPT +logmessages | {} +promisees | {} +-[ RECORD 3 ]---|-------------------------------------------------- +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:43:28+00 +changeoperation | CHANGE +policyfile | /var/cfengine/inputs/inventory/any.cf +releaseid | 05c0cc909d6709d816521d6cedbc4508894cc497 +promisehash | fd6d5... +namespace | default +bundlename | inventory_autorun +promisetype | methods +promiser | mtab +stackpath | /default/inventory_autorun/methods/'mtab'[0] +promisehandle | cfe_internal_autorun_inventory_mtab +promiseoutcome | KEPT +logmessages | {} +promisees | {} +``` + + + +## Table: PromiseLog + +History of promises executed on hosts. + +**Columns:** + +* **id** *(integer)* + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ChangeTimeStamp** *(timestamp)* + The GMT time on the host when this state was first perceived. + + **Note causes of change:** + - A change in the promise signature/hash for example, altering the promise + handle, promisees, or moving the promise to a different bundle + - A change in the policy releaseId (cf_promises_release_id) + - A change in promise outcome + +* **PolicyFile** *(text)* + Path to the file where the promise is located in. + +* **ReleaseId** *(text)* + Unique identifier of masterfiles version that is executed on the host. + +* **PromiseHash** *(text)* + Unique identifier of a promise. It is a hash of all promise attributes and their values. + +* **NameSpace** *(text)* + [Namespace][Namespaces] within which the promise is executed. If no namespace is set then it is set as: `default`. + +* **BundleName** *(text)* + [Bundle][Bundles] name where the promise is executed. + +* **PromiseType** *(text)* + [Type][Promise types] of the promise. + +* **Promiser** *(text)* + Object affected by a promise. + +* **StackPath** *(text)* + Call stack of the promise. + +* **PromiseHandle** *(text)* + A unique id-tag string for referring promise. + +* **PromiseOutcome** *(`KEPT`/`NOTKEPT`/`REPAIRED`)* + Promise execution result. + * `KEPT` - System has been found in the state as desired by the promise. CFEngine did not have to do any action to correct the state. + * `REPAIRED` - State of the system differed from the desired state. CFEngine took successful action to correct it according to promise specification. + * `NOTKEPT` - CFEngine has failed to converge the system according to the promise specification. + +* **LogMessages** *(text[])* + List of 5 last messages generated during promise execution. If the promise is `KEPT` the messages are not reported. Log messages can be used for tracking specific changes made by CFEngine while repairing or failing promise execution. + +* **Promisees** *(text[])* + List of [promisees][Promises] defined for the promise. + +**Example query:** + +```sql +SELECT hostkey, + policyfile, + releaseid, + promisehash, + namespace, + bundlename, + promisetype, + promiser, + stackpath, + promisehandle, + promiseoutcome, + logmessages, + promisees, + changetimestamp +FROM promiselog; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------- +hostkey | SHA=70138d580b9fd292ff856746df2fe7f9ded29db9ffca0c4d83acbbb97cde4d42 +policyfile | /var/cfengine/inputs/lib/bundles.cf +releaseid | f90866033a826aa05cf10fdc8d34a532a9cd465b +promisehash | 04659a0501f471eb1794cead6cd7a3291b78dcb195063821a7dcb4dbe7f7f804 +namespace | default +bundlename | prunedir +promisetype | files +promiser | /var/cfengine/outputs +stackpath | /default/cfe_internal_management/methods/'CFEngine_Internals'/default/cfe_internal_core_main/methods/'any'/default/cfe_internal_log_rotation/methods/'Prune old log files'/default/prunedir/files/'/var/cfengine/output +s'[1] +promisehandle | +promiseoutcome | REPAIRED +logmessages | {"Deleted file '/var/cfengine/outputs/cf_demohub_a10042_cfengine_com__1535846669_Sun_Sep__2_00_04_29_2018_0x7f4da3549700'"} +promisees | {} +changetimestamp | 2018-10-02 00:04:52+00 +``` + +## Table: Software + +Software packages installed (according to local package manager) on the hosts. +More information about CFEngine and package management can be found [here][packages]. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **SoftwareName** *(text)* + Name of installed software package. + +* **SoftwareVersion** *(text)* + Software package version. + +* **SoftwareArchitecture** *(text)* + Architecture. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp when the package was discovered / installed on the host. + +**Example query:** + +```sql +SELECT hostkey, + softwarename, + softwareversion, + softwarearchitecture, + changetimestamp +FROM software; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------|----------------------- +hostkey | SHA=a4dd5... +softwarename | libgssapi-krb5-2 +softwareversion | 1.12+dfsg-2ubuntu4.2 +softwarearchitecture | default +changetimestamp | 2015-03-12 10:20:18+00 +-[ RECORD 2 ]--------|----------------------- +hostkey | SHA=a4dd5... +softwarename | whiptail +softwareversion | 0.52.15-2ubuntu5 +softwarearchitecture | default +changetimestamp | 2015-03-12 10:20:18+00 +-[ RECORD 3 ]--------|----------------------- +hostkey | SHA=a4dd5... +softwarename | libruby1.9.1 +softwareversion | 1.9.3.484-2ubuntu1.2 +softwarearchitecture | default +changetimestamp | 2015-03-12 10:20:18+00 +``` + +## Table: SoftwareUpdates + +Patches available for installed packages on the hosts (as reported by local package manager). +The most up to date patch will be listed. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **PatchName** *(text)* + Name of the software. + +* **PatchVersion** *(text)* + Patch version. + +* **PatchArchitecture** *(text)* + Architecture of the patch. + +* **PatchReportType** *(`INSTALLED`/`AVAILABLE`)* + Patch status (`INSTALLED` status is specific only to SUSE Linux). + +* **ChangeTimeStamp** *(timestamp)* + Timestamp when the new patch / version was discovered as available on the host. + +**Example query:** + +```sql +SELECT hostkey, + patchname, + patchversion, + patcharchitecture, + patchreporttype, + changetimestamp +FROM softwareupdates; +``` + +**Output:** + +``` +-[ RECORD 1 ]-----|------------------------ +hostkey | SHA=a4dd5... +patchname | libelf1 +patchversion | 0.158-0ubuntu5.2 +patcharchitecture | default +patchreporttype | AVAILABLE +changetimestamp | 2015-03-12 10:20:18+00 +-[ RECORD 2 ]-----|------------------------ +hostkey | SHA=a4dd5... +patchname | libisccfg90 +patchversion | 1:9.9.5.dfsg-3ubuntu0.2 +patcharchitecture | default +patchreporttype | AVAILABLE +changetimestamp | 2015-03-12 10:20:18+00 +-[ RECORD 3 ]-----|------------------------ +hostkey | SHA=a4dd5... +patchname | libc6-dev +patchversion | 2.19-0ubuntu6.6 +patcharchitecture | default +patchreporttype | AVAILABLE +changetimestamp | 2015-03-12 10:20:18+00 +``` + +## Table: SoftwareLog +Software packages installed / deleted over period of time. +More information about CFEngine and package management can be found [here][packages]. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp when the package state was discovered on the host. + **Note:** The statement if true till present time or newer entry claims otherwise. + +* **ChangeOperation** *(`ADD`,`REMOVE`)* + CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. + * `ADD` - New package have been detected / installed. Package upgrate is considered as installing a new package with a different version. + * `REMOVE` - Package have been detected to be removed / uninstalled. During upgrate older version of the package is removed and reported as so. + +* **SoftwareName** *(text)* + Name of installed software package. + +* **SoftwareVersion** *(text)* + Software package version. + +* **SoftwareArchitecture** *(text)* + Architecture. + +**Example query:** + +```sql +SELECT hostkey, + changetimestamp, + changeoperation, + softwarename, + softwareversion, + softwarearchitecture +FROM softwarelog; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------|----------------------- +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +softwarename | libgssapi-krb5-2 +softwareversion | 1.12+dfsg-2ubuntu4.2 +softwarearchitecture | default +-[ RECORD 2 ]--------|----------------------- +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +softwarename | whiptail +softwareversion | 0.52.15-2ubuntu5 +softwarearchitecture | default +-[ RECORD 3 ]--------|----------------------- +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +softwarename | libruby1.9.1 +softwareversion | 1.9.3.484-2ubuntu1.2 +softwarearchitecture | default +``` + +## Table: SoftwareUpdatesLog + +**This table was deprecated in 3.7.0. It is no longer used.** + +Patches available for installed packages on the hosts (as reported by local package manager) over period of time. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp when the patch state was discovered on the host. + **Note:** The statement if true till present time or newer entry claims otherwise. + +* **ChangeOperation** *(`ADD`,`REMOVE`)* + CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. + * `ADD` - New patch have been detected. This is a common in case of release of new patch version or new package was installed that have an upgrate available. + * `REMOVE` - Patch is not longer available. Patch may be replaced with newer version, or installed package have been upgrated. + **Note:** CFEngine reports only the most up to date version available. + +* **PatchName** *(text)* + Name of the software. + +* **PatchVersion** *(text)* + Patch version. + +* **PatchArchitecture** *(text)* + Architecture of the patch. + +* **PatchReportType** *(`INSTALLED`/`AVAILABLE`)* + Patch status (`INSTALLED` status is specific only to SUSE Linux). + +**Example query:** + +```sql +SELECT hostkey, + changetimestamp, + changeoperation, + patchname, + patchversion, + patcharchitecture, + patchreporttype +FROM softwareupdateslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]-----|------------------------ +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +patchname | libelf1 +patchversion | 0.158-0ubuntu5.2 +patcharchitecture | default +patchreporttype | AVAILABLE +-[ RECORD 2 ]-----|------------------------ +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +patchname | libisccfg90 +patchversion | 1:9.9.5.dfsg-3ubuntu0.2 +patcharchitecture | default +patchreporttype | AVAILABLE +-[ RECORD 3 ]-----|------------------------ +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +patchname | libc6-dev +patchversion | 2.19-0ubuntu6.6 +patcharchitecture | default +patchreporttype | AVAILABLE +``` + +## Table: Status + +Statuses of report collection. cf-hub records all collection attempts and whether they are FAILEDC or CONSUMED. CONSUMED means next one will be delta. FAILEDC means next one will be REBASE. + +**Columns:** + +* **host** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ts** *(timestamp)* + Timestamp of last data provided by client during report collection. This is used by delta queries to request a start time. + +* **status** *(`FAILEDC`,`CONSUMED`)* + CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. + * `FAILEDC` - New patch have been detected. This is a common in case of release of new patch version or new package was installed that have an upgrate available. + * `CONSUMED` - Patch is not longer available. Patch may be replaced with newer version, or installed package have been upgrated. + **Note:** CFEngine reports only the most up to date version available. + +* **lstatus** *(text)* + Deprecated + +* **type** *(text)* + Deprecated + +* **who** *(integer)* + Deprecated + +* **whr** *integer* + Deprecated + +**Example query:** + +```sql +SELECT hostkey, + changetimestamp, + changeoperation, + patchname, + patchversion, + patcharchitecture, + patchreporttype +FROM softwareupdateslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]-----|------------------------ +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +patchname | libelf1 +patchversion | 0.158-0ubuntu5.2 +patcharchitecture | default +patchreporttype | AVAILABLE +-[ RECORD 2 ]-----|------------------------ +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +patchname | libisccfg90 +patchversion | 1:9.9.5.dfsg-3ubuntu0.2 +patcharchitecture | default +patchreporttype | AVAILABLE +-[ RECORD 3 ]-----|------------------------ +hostkey | SHA=3b94d... +changetimestamp | 2015-03-10 13:38:14+00 +changeoperation | ADD +patchname | libc6-dev +patchversion | 2.19-0ubuntu6.6 +patcharchitecture | default +patchreporttype | AVAILABLE +``` + + +## Table: Variables + +Variables and their values set on hosts at their last reported cf-agent execution. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **NameSpace** *(text)* + [Namespace][Namespaces] within which the variable is set. If no namespace is set then it is set as: `default`. + +* **Bundle** *(text)* + [Bundle][Bundles] name where the variable is set. + +* **VariableName** *(text)* + Name of the variable. + +* **VariableValue** *(text)* + Variable value serialized to string. + * List types such as: `slist`, `ilist`, `rlist` are serialized with CFEngine list format: {'value','value'}. + * `Data` type is serialized as JSON string. + +* **VariableType** *(text)* + Type of the variable. [List][Variables] of supported variable types. + +* **MetaTags** *(text[])* + List of [meta tags][Tags for variables, classes, and bundles] set for the variable. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp since when variable is set in its current form. + **Note:** If any of variable attributes change such as its `VariableValue` or `Bundle`, the timestamp will be updated. + +**Example query:** + +```sql +SELECT hostkey, + namespace, + bundle, + variablename, + variablevalue, + variabletype, + metatags, + changetimestamp +FROM variables; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|------------------------------------------------------------- +hostkey | SHA=a4dd5... +namespace | default +bundle | cfe_autorun_inventory_memory +variablename | total +variablevalue | 490.00 +variabletype | string +metatags | {source=promise,inventory,"attribute_name=Memory size (MB)"} +changetimestamp | 2015-03-11 09:51:41+00 +-[ RECORD 2 ]---|------------------------------------------------------------- +hostkey | SHA=a4dd5... +namespace | default +bundle | cfe_autorun_inventory_listening_ports +variablename | ports +variablevalue | {'22','111','5308','38854','50241'} +variabletype | slist +metatags | {source=promise,inventory,"attribute_name=Ports listening"} +changetimestamp | 2015-03-11 09:51:41+00 +-[ RECORD 3 ]---|------------------------------------------------------------- +hostkey | SHA=a4dd5... +namespace | default +bundle | cfe_autorun_inventory_memory +variablename | free +variablevalue | 69.66 +variabletype | string +metatags | {source=promise,report} +changetimestamp | 2015-03-11 14:27:12+00 +``` + +## Table: Variables_dictionary + +Inventory attributes, these data are using in [List of inventory attributes API][Inventory API#List of inventory attributes] + +**Columns:** + +* **Id** *(integer)* + Auto incremental ID +* **Attribute_name** *(text)* + Attribute name +* **Category** *(text)* *(`Hardware`,`Software`,`Network`, `Security`, `User defined`)* + Attribute category +* **Readonly** *(integer)* *(`0`,`1`)* + Is attribute readonly +* **Type** *(text)* + Type of the attribute. [List][Variables] of supported variable types. +* **convert_function** *(text)* + Convert function. Emp.: `cf_clearSlist` - to transform string like `{"1", "2"}` to `1, 2` +* **keyname** *(text)* + Key name +* **Enabled** *(integer)* *(`0`,`1`)* + Is attribute enabled for the API + +**Example query:** + +```sql +SELECT attribute_name, + category, + readonly, + type, + convert_function, + enabled +FROM variables_dictionary; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|----------------------------------------------------- +attribute_name | Architecture +category | Software +readonly | 1 +type | string +convert_function| +enabled | 1 +-[ RECORD 2 ]---|----------------------------------------------------- +attribute_name | IPv4 addresses +category | Network +readonly | 1 +type | slist +convert_function| cf_clearSlist +enabled | 1 +``` + +## Table: VariablesLog + +CFEngine variables set on hosts by CFEngine over period of time. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect data concerning same hosts. + +* **ChangeTimeStamp** *(timestamp)* + Timestamp since when variable is set in its current form. + **Note:** The statement if true till present time or newer entry claims otherwise. + +* **ChangeOperation** *(`ADD`,`CHANGE`,`REMOVE`,`UNTRACKED`)* + CFEngine uses incremental diffs to report it's state. `ChangeOperation` is a diff state describing current entry. + * `ADD` - stands for introducing a new entry which did not exist before. In this case, new CFEngine variable have been introduced. + * `CHANGE` - stands for changing value or attribute such as `VariableValue` or `MetaTags` have changed. + * `REMOVE` - Variable have not been set. + * `UNTRACKED` - CFEngine provides a mechanism for filtering unwanted data from being reported. `UNTRACKED` marker states that information is being filtered and will not report any future information about it. + +* **NameSpace** *(text)* + [Namespace][Namespaces] within which the variable is set. If no namespace is set then it is set as: `default`. + +* **Bundle** *(text)* + [Bundle][Bundles] name where the variable is set. + +* **VariableName** *(text)* + Name of the variable. + +* **VariableValue** *(text)* + Variable value serialized to string. + * List types such as: `slist`, `ilist`, `rlist` are serialized with CFEngine list format: {'value','value'}. + * `Data` type is serialized as JSON string. + +* **VariableType** *(text)* + Type of the variable. [List][Variables] of supported variable types. + +* **MetaTags** *(text[])* + List of [meta tags][Tags for variables, classes, and bundles] set for the variable. + +**Example query:** + +```sql +SELECT hostkey, + changetimestamp, + changeoperation, + namespace, + bundle, + variablename, + variablevalue, + variabletype, + metatags +FROM variableslog; +``` + +**Output:** + +``` +-[ RECORD 1 ]---|----------------------------------------------------- +hostkey | SHA=2aab8... +changetimestamp | 2015-03-10 13:43:00+00 +changeoperation | CHANGE +namespace | default +bundle | mon +variablename | av_cpu +variablevalue | 0.06 +variabletype | string +metatags | {monitoring,source=environment} +-[ RECORD 2 ]---|----------------------------------------------------- +hostkey | SHA=2aab8... +changetimestamp | 2015-03-10 13:40:20+00 +changeoperation | ADD +namespace | default +bundle | sys +variablename | arch +variablevalue | x86_64 +variabletype | string +metatags | {inventory,source=agent,attribute_name=Architecture} +-[ RECORD 3 ]---|----------------------------------------------------- +hostkey | SHA=2aab8... +changetimestamp | 2015-03-10 13:43:00+00 +changeoperation | CHANGE +namespace | default +bundle | mon +variablename | av_diskfree +variablevalue | 67.01 +variabletype | string +metatags | {monitoring,source=environment} +``` +## Table: v_hosts + +V_hosts table contains information about hosts. + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect + data concerning same hosts. + +* **iscallcollected** *(boolean)* + Is host call collected + +* **LastReportTimeStamp** *(timestamp)* + Timestamp of the most recent successful report collection. + +* **FirstReportTimeStamp** *(timestamp)* + Timestamp when the host reported to the hub for the first time, which + indicate when the host was bootstrapped to the hub. + +**Example query:** + +```sql +SELECT hostkey, + iscallcollected, + lastreporttimestamp, + firstreporttimestamp +FROM hosts; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------|----------------------- +hostkey | SHA=a4dd... +iscallcollected | t +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +-[ RECORD 2 ]--------|----------------------- +hostkey | SHA=3b94... +iscallcollected | f +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:34:20+00 +-[ RECORD 3 ]--------|----------------------- +hostkey | SHA=2aab... +iscallcollected | f +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +``` + +## Table: vm_hosts + +vm_hosts table contains basic information about hosts managed by CFEngine. +In this table data are cached what gives a better query performance + +**Columns:** + +* **HostKey** *(text)* + Unique host identifier. All tables can be joined by `HostKey` to connect + data concerning same hosts. + +* **HostName** *(text)* + Host name locally detected on the host, configurable as `hostIdentifier` + option in [Settings API][Status and settings REST API#Get settings] and + Mission Portal settings UI. + +* **IPAddress** *(text)* + IP address of the host derived from the lastseen database (this is expected + to be the IP address from which connections come from, beware NAT will cause + multiple hosts to appear to have the same IP address). + +* **LastReportTimeStamp** *(timestamp)* + Timestamp of the most recent successful report collection. + +* **FirstReportTimeStamp** *(timestamp)* + Timestamp when the host reported to the hub for the first time, which + indicate when the host was bootstrapped to the hub. + +**Example query:** + +```sql +SELECT hostkey, + hostname, + ipaddress, + lastreporttimestamp, + firstreporttimestamp +FROM hosts; +``` + +**Output:** + +``` +-[ RECORD 1 ]--------|----------------------- +hostkey | SHA=a4dd... +hostname | host001 +ipaddress | 192.168.56.151 +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +-[ RECORD 2 ]--------|----------------------- +hostkey | SHA=3b94... +hostname | hub +ipaddress | 192.168.56.65 +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:34:20+00 +-[ RECORD 3 ]--------|----------------------- +hostkey | SHA=2aab... +hostname | host002 +ipaddress | 192.168.56.152 +lastreporttimestamp | 2015-03-10 14:20:20+00 +firstreporttimestamp | 2015-03-10 13:40:20+00 +``` diff --git a/api/enterprise-api-ref/sql-schema/cfmp.markdown b/api/enterprise-api-ref/sql-schema/cfmp.markdown new file mode 100644 index 000000000..5e053e8d9 --- /dev/null +++ b/api/enterprise-api-ref/sql-schema/cfmp.markdown @@ -0,0 +1,469 @@ +--- +layout: default +title: cfmp +published: true +--- + +This database contains Mission Portal related settings not processed by the API. + +## Table: app + +Information about Mission Portal applications. + +**Columns:** + +* **displayindex** *(integer)* + The display order of the app in the Mission Portal menu. +* **filepath** *(text)* + The path of the app module in the application directory. +* **hascontroller** *(integer)* + The flag that indicates whether the app has a controller file or not. +* **icon** *(character varying(50))* + The name of the app icon file in the images directory. +* **meta** *(json)* + The JSON object that stores the app metadata, such as name, description, license, etc. +* **showappslist** *(integer)* + The flag that indicates whether the app is visible in the Mission Portal menu or not. +* **state** *(integer)* + The state of the app, such as 1 or 0. +* **url** *(text)* + The URL of the app in the Mission Portal. +* **id** *(character varying(100))* + The unique identifier of the app, used as the primary key. +* **rbac_id** *(character varying(50))* + The identifier of the RBAC permission that the app requires, may be null. + +## Table: astrolabeprofile + +Information about Host trees such as who it was created by, who it is shared with and the definition of the host tree. + +**Columns:** + +* **id** *(integer)* + The unique identifier of the profile, generated from a sequence. +* **username** *(character varying(50))* + The username of the user who created or owns the profile. +* **profileid** *(character varying(50))* + The name of the profile, such as OS, Services, etc. +* **defaulttree** *(boolean)* + The flag that indicates whether the profile is the default one for the user or not. +* **globaltree** *(boolean)* + The flag that indicates whether the profile is a global one for all users or not. +* **sharedpermission** *(character varying(50)[])* + The array of usernames that the profile is shared with, may be empty. +* **sharedby** *(character varying(50)[])* + The array of usernames that shared the profile with the user, may be empty. +* **data** *(json)* + The JSON object that stores the profile data, such as label, classRegex, children, etc. + +## Table: ci_sessions + +Information about current sessions. + +**Columns:** + +* **id** *(character varying(128))* + The unique identifier of the session, used as the primary key. +* **ip_address** *(character varying(45))* + The IP address of the user who initiated the session. +* **timestamp** *(bigint)* + The UNIX timestamp of the last activity of the session. +* **data** *(text)* + The text data of the session, encoded in base64. + +## Table: compliance_score + +Compliance reports score. + +**Columns:** + +* **report_id** *(integer)* + The id of the compliance report that the user has generated. +* **username** *(text)* + The name of the user who has generated the compliance report. +* **score** *(integer)* + The percentage of compliance checks that the user has passed. +* **update_ts** *(timestamp with time zone)* + The timestamp of the last update of the compliance report. +* **fail_checks** *(integer)* + The number of compliance checks that the user has failed. +* **total** *(integer)* + The total number of compliance checks that the user has performed. + +## Table: customization + +Stores Mission Portal UI customization config. + +**Columns:** + +* **key** *(character varying)* + The name of the customization option such as logo_on_login, login_text, header_color, etc. +* **value** *(text)* + The value of the customization option. + +## Table: dashboard_alerts + +User dashboards alerts status. + +**Columns:** + +* **id** *(integer)* + The primary key of the dashboard alerts table. +* **ruleid** *(integer)* + The id of the rule that triggered the alert. +* **failhosts** *(integer)* + The number of hosts that failed the rule. +* **lastcheck** *(integer)* + The timestamp of the last check of the rule. +* **lasteventtime** *(integer)* + The timestamp of the last event that caused the alert status to change. +* **laststatuschange** *(integer)* + The timestamp of the last change of the alert status. +* **servertime** *(integer)* + The timestamp of the server time when the alert was generated. +* **pause** *(integer)* + The timestamp indicating when the alert was paused. +* **paused** *(integer)* + A flag indicating whether the alert was paused by the user or not. +* **name** *(character varying(500))* + The name of the alert. +* **severity** *(character varying(10))* + The severity level of the alert, such as high, medium, or low. +* **site_url** *(text)* + The URL of the Mission Portal host where the alert is displayed. +* **status** *(character varying(32))* + The status of the alert, such as success, fail, or warning. +* **totalhosts** *(integer)* + The total number of hosts that are affected by the rule. +* **username** *(character varying(50))* + The name of the user who created the alert. +* **widgetname** *(character varying(100))* + The name of the widget that shows the alert. +* **emailtonotify** *(character varying(100))* + The email address of the user who will be notified of the alert. +* **reminder** *(integer)* + The frequency of the reminder email for the alert. +* **widgetid** *(integer)* + The id of the widget that shows the alert. +* **hostcontextsprofileid** *(character varying(20))* + The id of the host contexts profile that defines the scope of the alert. +* **hostcontexts** *(json)* + A JSON object containing the host contexts that define the scope of the alert. +* **hostcontextspath** *(text)* + The path of the host contexts that define the scope of the alert. +* **excludedhosts** *(json)* + A JSON object describing hosts that should be excluded from checking the alert. + +## Table: dashboard_alerts_script + +Association of script with dashboard alert. + +**Columns:** + +* **alert_id** *(integer)* + The id of the dashboard alert that is associated with a script. +* **script_id** *(integer)* + The id of the script that is associated with a dashboard alert. + +## Table: dashboard_dashboards + +User dashboards and configuration. + +**Columns:** + +* **id** *(integer)* + The primary key of the dashboard table. +* **name** *(character varying(200))* + The name of the dashboard. +* **username** *(character varying(20))* + The name of the user who owns the dashboard. +* **public** *(integer)* + A flag indicating whether the dashboard is public or private. +* **widgets** *(character varying(200))* + A comma separated list of widget ids that are displayed on the dashboard. +* **sharedwith** *(jsonb)* + A JSON object containing the roles, users, and sharedWithAll flag that determine the sharing settings of the dashboard. + +## Table: dashboard_rules + +User-defined dashboard alert rules. + +**Columns:** + +* **id** *(integer)* + Unique identifier for the dashboard rule. +* **name** *(text)* + Name of the dashboard rule. +* **description** *(text)* + Description of the dashboard rule. +* **type** *(character varying(20))* + Type of the dashboard rule (e.g., policy, softwareupdate, inventory). +* **username** *(character varying(20))* + Username of the user who created the dashboard rule. +* **policyconditions** *(json)* + Dashboard rule conditions for checks based on promise outcomes such as KEPT, NOT_KEPT, and REPAIRED. (JSON object) +* **inventoryconditions** *(json)* + JSON object of conditions for inventory-based dashboard rules. +* **softwareupdateconditions** *(json)* + JSON object of conditions for software update-based dashboard rules. +* **category** *(text)* + Category assigned to the dashboard rule. +* **severity** *(text)* + Severity level assigned to the dashboard rule such as low, medium, high. +* **hostcontexts** *(json)* + JSON object describing the set of hosts the limiting the hosts that should be considered when checking the rule. If not set the condition is checked for against all hosts the user has access to based on RBAC and host reported data. +* **conditionmustbemet** *(boolean)* + Flag indicating whether conditions must be met for the dashboard rule. +* **customconditions** *(json)* + Custom dashboard conditions (for widgets), which use SQL queries returning hostkeys of affected hosts (JSON object). +* **filechangedconditions** *(json)* + File changed conditions for the dashboard rule. +* **export_id** *(text)* + Identifier for exporting dashboard rules. + +## Table: dashboard_scripts + +Table containing scripts available for association with alerts. + +**Columns:** + +* **id** *(integer)* + Unique identifier for the script entry. +* **name** *(text)* + Name of the script. +* **description** *(text)* + Description of the script. +* **script_name** *(text)* + Name of the actual script file. +* **type** *(text)* + Type of the script. (not used) + +## Table: dashboard_widgets + +User configurations for dashboard widgets. + +**Columns:** + +* **id** *(integer)* + Unique identifier for the dashboard widget. +* **name** *(character varying(500))* + Name of the dashboard widget. +* **type** *(character varying(20))* + Type of the dashboard widget (e.g., inventory, alerts, hostCount). +* **username** *(character varying(50))* + Username of the user who configured the dashboard widget. +* **ordering** *(integer)* + Ordering of the dashboard widget in the dashboard. +* **dashboardid** *(integer)* + Identifier for the associated dashboard. +* **payload** *(jsonb)* + JSON payload containing additional configuration for the dashboard widget. +## Table: eventslog + +Event logs. + +**Columns:** + +* **id** *(integer)* + Unique identifier for the event log entry. +* **username** *(character varying(100))* + Username associated with the event log entry. +* **item_id** *(character varying(100))* + Identifier associated with the item triggering the event (e.g., alert id). +* **item_type** *(character varying)* + Type of the item triggering the event (e.g., host, alerts). +* **item_name** *(character varying(500))* + Name of the item triggering the event. +* **tags** *(character varying(500)[])* + Tags associated with the event log entry. +* **time** *(timestamp without time zone)* + Timestamp when the event occurred. +* **severity** *(character varying(20))* + Severity level of the event such as low, medium, high. Not all events specify a severity. +* **message** *(text)* + Detailed message describing the event. +* **status** *(character varying(10))* + Status of the event (e.g., triggered, cleared). + +## Table: favourite_reports + +Table associating favorited reports with users. + +**Columns:** + +* **report_id** *(bigint)* + Identifier of the favorite report. +* **username** *(text)* + Username of the user who marked the report as a favorite. +* **created_at** *(timestamp with time zone)* + Timestamp indicating when the report was marked as a favorite. + +## Table: mail_settings + +Global email settings. + +**Columns:** + +* **key** *(character varying)* + Key representing a specific email setting. +* **value** *(text)* + Value associated with the email setting key. + +## Table: pinned_items + +Pinned inventory, class, or variable items. + +**Columns:** + +* **id** *(bigint)* + Unique identifier for the pinned item. +* **username** *(text)* + Username of the user who pinned the item. +* **type** *(pinned_type)* + Type of the pinned item (e.g., inventory, class, variable). +* **name** *(text)* + Name of the pinned item. +* **created_at** *(timestamp with time zone)* + Timestamp indicating when the item was pinned. + +## Table: report + +Information about saved reports. + +**Columns:** + +* **id** *(integer)* + The primary key of the report table. +* **username** *(character varying(50))* + The name of the user who saved the report. +* **url** *(character varying(500))* + The URL of the report. +* **reporttype** *(character varying(50))* + The type of the report, such as compliance, inventory, or software update. +* **reportcategory** *(character varying(50))* + The category of the report, such as security, performance, or other. +* **type** *(character varying(50))* + The format of the report, such as pdf or csv. +* **readonly** *(integer)* + A flag indicating whether the report is read-only or editable. +* **is_public** *(integer)* + A flag indicating whether the report is public or private. +* **can_subscribe** *(integer)* + A flag indicating whether the report can be subscribed to or not. +* **is_subscribed** *(integer)* + A flag indicating whether the user is subscribed to the report or not. +* **label** *(character varying(500))* + The label of the report. +* **date** *(timestamp without time zone)* + The date of the report. +* **params** *(text)* + The parameters of the report. +* **sharedpermission** *(character varying(50)[])* + A list of permissions that the report has been shared with. +* **sharedby** *(character varying(50)[])* + A list of users who have shared the report. +* **advancedreportsdata** *(json)* + A JSON object containing the advanced reports data. +* **export_id** *(text)* + The export id of the report, used for importing and exporting reports. +* **meta_data** *(jsonb)* + A JSON object containing the meta data of the report. + +## Table: report_schedule + +Information about scheduled reports. + +**Columns:** + +* **id** *(character varying(500))* + The unique identifier for the scheduled report. +* **reportid** *(integer)* + The foreign key referencing the associated report. +* **userid** *(character varying(50))* + The user ID associated with the scheduled report. +* **title** *(character varying(500))* + The title of the scheduled report. +* **description** *(character varying(500))* + The description of the scheduled report. +* **emailfrom** *(character varying(500))* + The email address from which the report is sent. +* **emailto** *(character varying(500))* + The email address to which the report is sent. +* **enabled** *(integer)* + Flag indicating whether the scheduled report is enabled. +* **query** *(text)* + The SQL query that defines the report for the scheduled task. +* **outputtypes** *(character varying(50)[])* + Array of output types for the scheduled report. +* **schedule*** *(character varying(500))* + The schedule for running the report. +* **schedulehumanreadabletime** *(character varying(500))* + Human-readable representation of the schedule time. +* **schedulename** *(character varying(500))* + The name associated with the schedule. +* **site_url** *(text)* + The URL associated with the scheduled report. +* **hostcontextsprofileid** *(character varying(20))* + The profile ID associated with the host contexts. +* **hostcontextspath** *(text)* + The path associated with the host contexts. +* **hostcontexts** *(json)* + JSON data representing the subset of hosts that the report should be filtered for. If not defined the scheduled report includes all hosts the userid is allowed to see based on RBAC and data reported by the host. +* **scheduledata** *(json)* + JSON data containing details about the schedule. +* **excludedhosts** *(json)* + JSON data representing excluded hosts for the scheduled report. +* **skipmailing** *(boolean)* + Flag indicating whether mailing is skipped for the scheduled report. + +## Table: users + +User preferences and information about Mission Portal behavior. + +**Columns:** + +* **id** *(integer)* + The primary key of the user table. +* **username** *(character varying(50))* + The unique name of the user. +* **source** *(character varying(20))* + The source of the user account, such as internal or external (e.g. LDAP, Active Directory). +* **last_login** *(timestamp without time zone)* + The timestamp of the last login of the user. +* **remember_code** *(character varying(50))* + The code used to remember the user login session. +* **dashboard** *(integer)* + The id of the default dashboard for the user. +* **seen_tour** *(smallint)* + A flag indicating whether the user has seen the tour of the Mission Portal. +* **seen_wizard** *(smallint)* + A flag indicating whether the user has seen the wizard of the Mission Portal. +* **never_ask_timezone_change** *(smallint)* + A flag indicating whether the user wants to be asked about changing the timezone. +* **use_browser_time** *(smallint)* + A flag indicating whether the user wants to use the browser time or the server time. +* **dark_mode** *(smallint)* + A flag indicating whether the user prefers the dark mode or the light mode. +* **pinned_items_version** *(smallint)* + This is used to add default pinned items which are added after this version. +* **additional_data** *(jsonb)* + A JSON object containing additional data about the user preferences and behavior. + +## Table: variables_dictionary + +Information about reported inventory attributes. + +**Columns:** + +* **id** *(integer)* + The unique identifier for the variable in the dictionary. +* **attribute_name** *(character varying(200))* + The name of the attribute represented by the variable. +* **category** *(character varying(200))* + The category to which the attribute belongs. +* **readonly** *(integer)* + Flag indicating whether the attribute is read-only. +* **type** *(character varying(200))* + The data type of the attribute such as string, slist, int, real. +* **convert_function** *(character varying(200))* + The conversion function applied to the attribute such as cf_clearslist (if any). diff --git a/api/enterprise-api-ref/sql-schema/cfsettings.markdown b/api/enterprise-api-ref/sql-schema/cfsettings.markdown new file mode 100644 index 000000000..62b0aad60 --- /dev/null +++ b/api/enterprise-api-ref/sql-schema/cfsettings.markdown @@ -0,0 +1,419 @@ +--- +layout: default +title: cfsettings +published: true +--- + +Settings used by Mission Portal APIs, no reported data. + +## Table: build_modules + +Information about build modules available from the index (build.cfengine.com). + +**Columns:** + +* **name** *(text)* + The name of the build module. +* **readme** *(text)* + The readme file content of the build module in HTML. +* **description** *(text)* + The description of the build module. +* **version** *(text)* + The version of the build module. +* **author** *(jsonb)* + The author information of the build module as a JSON object with keys such as url, name, image. +* **updated** *(timestamp with time zone)* + The last updated time of the build module. +* **downloads** *(integer)* + The number of downloads of the build module. +* **repo** *(text)* + The repository URL of the build module. +* **documentation** *(text)* + The documentation URL of the build module. +* **website** *(text)* + The website URL of the build module. +* **subdirectory** *(text)* + The subdirectory of the build module in the repository. +* **commit** *(text)* + The commit hash of the build module. +* **dependencies** *(jsonb)* + The dependencies of the build module as a JSON object. +* **tags** *(jsonb)* + The tags of the build module as a JSON object. +* **versions** *(jsonb)* + The available versions of the build module as a JSON object. +* **latest** *(boolean)* + A flag indicating whether the build module is the latest version. +* **ts_vector** *(tsvector)** + Generated ts_vector column based on id and description. + +## Table: build_projects + +Build application projects. + +**Columns:** + +* **id** *(bigint)* + The unique identifier of the build project, generated from a sequence. +* **repository_url** *(text)* + The URL of the git repository that contains the build project. +* **branch** *(text)* + The branch of the git repository that the build project uses. +* **name** *(text)* + The name of the build project, derived from the repository URL and branch. +* **authentication_type** *(authentication_types)* + The type of authentication that the build project uses to access the git repository. Must match authentication_types such as password or private_key. +* **username** *(text)* + The username that the build project uses to access the git repository, if applicable. +* **password** *(text)* + The password that the build project uses to access the git repository, if applicable. +* **ssh_private_key** *(text)* + This field is not used. Ref ENT-11330. +* **ssh_key_id** *(integer)* + The foreign key that references the ssh_keys table, if applicable. +* **created_at** *(timestamp with time zone)* + The timestamp of when the build project was created. +* **pushed_at** *(timestamp with time zone)* + The timestamp of when the build project was last pushed to the git repository. +* **is_local** *(boolean)* + The flag that indicates whether the build project is local or remote. +* **is_deployed_locally** *(boolean)* + The flag that indicates whether the build project is deployed locally or not. +* **action** *(text)* + The action that the build project performs, such as push, pushAndDeploy, localDeploy. + +## Table: cfbs_requests + +cfbs requests and responses handled by cf-reactor. + +**Columns:** + +* **id** *(bigint)* + The unique identifier of the cfbs request, generated from a sequence. +* **request_name** *(text)* + The name of the cfbs request, such as init_project, local_deploy, etc. +* **arguments** *(jsonb)* + The JSONB object that stores the arguments of the cfbs request, such as git, project_id, etc. +* **created_at** *(timestamp with time zone)* + The timestamp of when the cfbs request was created. +* **finished_at** *(timestamp with time zone)* + The timestamp of when the cfbs request was finished, may be null if the request is still in progress. +* **response** *(jsonb)* + The JSONB object that stores the response of the cfbs request, such as status, details, etc. + +## Table: external_roles_map + +Map of external directory group to Mission Portal RBAC role for automatic association of directory users to Mission Portal roles. + +**Columns:** + +* **external_role** *(text)* + The name of the external directory (LDAP/Active Directory) group. +* **internal_role** *(text)* + The name of the internal Mission Portal role, such as admin, auditor, or guest. +* **changetimestamp** *(timestamp with time zone)* + The timestamp of when the mapping was last changed. + +## Table: federated_reporting_settings + +Federated reporting settings when enabled. + +**Columns:** + +* **key** *(character varying)* + The name of the federated reporting setting, such as enable_as, enable_request_sent, or target_state. +* **value** *(text)* + The value of the federated reporting setting, such as superhub, 1, or on. + +## Table: inventory_aliases + +Inventory attributes aliases. + +**Columns:** + +* **inventory_attribute** *(text)* + The name of the inventory attribute, such as Kernel, Kernel Release, etc. +* **alias** *(text)* + The alias of the inventory attribute, such as os type, os kernel, etc. + +## Table: keyspendingfordeletion + +Keys of deleted hosts yet to be deleted. + +**Columns:** + +* **hostkey** *(text)* + The key of the host that was deleted from the database but not yet from the ppkeys directory. + +## Table: licenseinfo + +Information about the currently installed license. + +**Columns:** + +* **expiretimestamp** *(timestamp with time zone)* + The timestamp of when the license expires. +* **installtimestamp** *(timestamp with time zone)* + The timestamp of when the license was installed. +* **organization** *(text)* + The name of the organization that owns the license. +* **licensetype** *(text)* + The type of the license such as Enterprise. +* **licensecount** *(integer)* + The number of hosts that the license covers. + +## Table: oauth_access_tokens + +OAuth access tokens and expiration. + +**Columns:** + +* **access_token** *(character varying(40))* + The access token that grants access to the OAuth client. +* **client_id** *(character varying(80))* + The client identifier of the OAuth client that obtained the access token. +* **user_id** *(character varying(255))* + The user identifier of the user that authorized the access token. +* **expires** *(timestamp without time zone)* + The timestamp of when the access token expires. +* **scope** *(character varying(2000))* + The scope of access that the access token grants. + +## Table: oauth_authorization_codes + +OAuth authorizations. + +**Columns:** + +* **authorization_code** *(character varying(40))* + The authorization code that grants access to the OAuth client. +* **client_id** *(character varying(80))* + The client identifier of the OAuth client that requested the authorization code. +* **user_id** *(character varying(255))* + The user identifier of the user that authorized the OAuth client. +* **redirect_uri** *(character varying(2000))* + The URI that the OAuth client will redirect to after obtaining the authorization code. +* **expires** *(timestamp without time zone)* + The timestamp of when the authorization code expires. +* **scope** *(character varying(2000))* + The scope of access that the authorization code grants. + +## Table: oauth_clients + +OAuth clients. + +**Columns:** + +* **client_id** *(character varying(80))* + The unique identifier of the OAuth client. +* **client_secret** *(character varying(80))* + The secret key of the OAuth client. +* **redirect_uri** *(character varying(2000))* + The URI that the OAuth client will redirect to after authorization. +* **grant_types** *(character varying(80))* + The grant types that the OAuth client supports, such as authorization_code, password, etc. +* **scope** *(character varying(100))* + The scope of access that the OAuth client requests, such as read, write, etc. +* **user_id** *(character varying(80))* + The user identifier that the OAuth client is associated with. + +## Table: oauth_jwt + +OAuth JSON Web Tokens. + +**Columns:** + +* **client_id** *(character varying(80))* + The client identifier of the OAuth client that uses JSON Web Tokens. +* **subject** *(character varying(80))* + The subject of the JSON Web Token, usually the user identifier. +* **public_key** *(character varying(2000))* + The public key of the OAuth client that verifies the JSON Web Token signature. + +## Table: oauth_refresh_tokens + +OAuth token expiration. + +**Columns:** + +* **refresh_token** *(character varying(40))* + The refresh token that can be used to obtain a new access token. +* **client_id** *(character varying(80))* + The client identifier of the OAuth client that obtained the refresh token. +* **user_id** *(character varying(255))* + The user identifier of the user that authorized the OAuth client. +* **expires** *(timestamp without time zone)* + The timestamp of when the refresh token expires. +* **scope** *(character varying(2000))* + The scope of access that the refresh token grants. + +## Table: oauth_scopes + +OAuth scopes. + +**Columns:** + +* **scope** *(text)* + The name of the OAuth scope, such as read, write, etc. +* **is_default** *(boolean)* + The flag that indicates whether the OAuth scope is the default scope for new clients. + +## Table: rbac_permissions + +RBAC permissions. + +**Columns:** + +* **alias** *(character varying(100))* + The unique alias of the RBAC permission, used as the primary key. +* **group** *(character varying(50))* + The group that the RBAC permission belongs to, such as Inventory API, Changes API, Events API, Hosts, etc. +* **name** *(character varying(100))* + The name of the RBAC permission, such as Get inventory report, Get event list, etc. +* **description** *(character varying(200))* + The description of the RBAC permission, explaining what it does and why it is needed. +* **application** *(character varying(50))* + The application that the RBAC permission applies to, such as API, Mission Portal, etc. +* **allowed_by_default** *(boolean)* + The flag that indicates whether the RBAC permission is allowed by default for new roles, defaults to false. + +## Table: rbac_role_permission + +This table associates roles to permissions in a 1-to-many relationship. + +**Columns:** + +* **role_id** *(character varying)* + The name of the role that has the permission. +* **permission_alias** *(character varying)* + The alias of the permission that the role has. + +## Table: remote_hubs + +Information about federated reporting feeder hubs when federated reporting has been enabled. + +**Columns:** + +* **id** *(bigint)* + The unique identifier of the remote hub, generated from a sequence. +* **hostkey** *(text)* + The host key of the remote hub. +* **ui_name** *(character varying(70))* + The user-friendly name of the remote hub, must be unique among all remote hubs. +* **api_url** *(text)* + The URL of the remote hub API, used for communication and data transfer. +* **target_state** *(character varying(20))* + The desired state of the remote hub such as on, paused. +* **transport** *(json)* + The JSON object that stores the transport settings of the remote hub with keys such as mode, ssh_user, ssh_host, ssh_pubkey. +* **role** *(character varying(50))* + The role of the remote hub, such as feeder or superhub. + +## Table: roles + +Role definitions that manage host visibility. + +**Columns:** + +* **name** *(text)* + The name of the role, must be unique and not null. +* **description** *(text)* + The description of the role. +* **include_rx** *(text)* + The regular expression that matches classes reported by the host governing what the role can see. +* **exclude_rx** *(text)* + The regular expression that matches classes reported by the host governing what the role cannot see. +* **changetimestamp** *(timestamp with time zone)* + The timestamp of when the role was last change. +* **is_default** *(boolean)* + The boolean flag that indicates whether the role is the default role for new users, defaults to false. + +## Table: scheduledreports + +Users scheduled reports. + +**Columns:** + +* **username** *(text)* + The username of the user who scheduled the report. +* **query** *(text)* + The SQL query that defines the report. +* **query_id** *(text)* + The unique identifier of the query. +* **run_classes** *(text)* + A CFEngine class expression (without ::) such as (January|February|March|April|May|June|July|August|September|October|November|December).GMT_Hr22.Min50_55 describing when the report should be run. +* **last_executed** *(text)* + The timestamp of when the report was last executed. +* **email** *(text)* + The email address of the user who scheduled the report. +* **email_title** *(text)* + The title of the email that contains the report. +* **email_description** *(text)* + The description which is present in the email providing the report. +* **host_include** *(text[])* + The array of hosts that the report should include. +* **host_exclude** *(text[])* + The array of hosts that the report should exclude (overriding inclusions). +* **already_run** *(boolean)* + The boolean flag that indicates whether the report has already run or not. +* **enabled** *(boolean)* + The boolean flag that indicates whether the report is enabled or not. +* **output** *(text[])* + The array of output formats (csv, pdf) that the report should generate. +* **excludedhosts** *(json)* + The JSON object that stores the hosts that are excluded from the report. + +## Table: settings + +User settings and preferences for RBAC, host not reporting threshold, collision threshold (duplicate host indicator), and Enterprise API log level. Populated when non-default settings are saved. + +**Columns:** + +* **key** *(text)* + The Key of the setting. +* **value** *(json)* + The value of the setting. + +## Table: ssh_keys + +Generated ssh keys. + +**Columns:** + +* **id** *(bigint)* + The unique identifier of the ssh key, generated from a sequence. +* **public_key** *(text)* + The public key of the ssh key, used for authentication and encryption. +* **private_key** *(text)* + The private key of the ssh key, used for decryption and signing. +* **generated_at** *(timestamp with time zone)* + The timestamp of when the ssh key was generated, defaults to the current time. +* **generated_by** *(text)* + The username of the user who generated the ssh key. + +## Table: users + +User settings (name, email, password, timezone, provenance) and roles associated with the user. + +**Columns:** + +* **username** *(text)* + The username of the user. +* **password** *(text)* + The hashed password of the user. +* **salt** *(text)* + The salt used to hash the password of the user. +* **name** *(text)* + The name of the user. +* **email** *(text)* + The email address of the user. +* **external** *(boolean)* + The boolean flag that indicates whether the user is an external user or not, defaults to false. +* **active** *(boolean)* + The boolean flag that indicates whether the user is active or not, defaults to false. +* **roles** *(text[])* + The array of roles that the user has, defaults to an empty array. +* **time_zone** *(text)* + The timestamp of when the user settings were last changed. +* **changetimestamp** *(timestamp with time zone)* + The time zone of the user, defaults to Etc/GMT+0. diff --git a/api/enterprise-api-ref/ssh-keys-api.markdown b/api/enterprise-api-ref/ssh-keys-api.markdown index b76100925..6b30fdad7 100644 --- a/api/enterprise-api-ref/ssh-keys-api.markdown +++ b/api/enterprise-api-ref/ssh-keys-api.markdown @@ -2,14 +2,13 @@ layout: default title: SSH keys API published: true -tags: [reference, enterprise, API, build, SSH] --- The SSH keys API enables you to generate a key pair that can be used for authorization. -# SSH keys API +## SSH keys API -## Generate SSH key +### Generate SSH key Generates a key with 4096 bits, sha2-512 digest and in rfc4716 (default openssh) format. @@ -42,7 +41,7 @@ HTTP 200 Ok | 200 OK | SSH key successfully created | | 500 Internal server error | Internal server error | -## Get SSH keys list +### Get SSH keys list **URI:** https://hub.cfengine.com/api/ssh-key @@ -83,7 +82,7 @@ HTTP 200 OK | 200 Ok | Successful response | | 500 Internal server error | Internal server error | -## Get SSH key +### Get SSH key **URI:** https://hub.cfengine.com/api/ssh-key/:id @@ -122,7 +121,7 @@ HTTP 200 OK | 404 Not found | SSH key not found | | 500 Internal server error | Internal server error | -## Delete SSH key +### Delete SSH key **URI:** https://hub.cfengine.com/api/ssh-key/:id diff --git a/api/enterprise-api-ref/status-settings.markdown b/api/enterprise-api-ref/status-settings.markdown index bed2c914d..378b71d8f 100644 --- a/api/enterprise-api-ref/status-settings.markdown +++ b/api/enterprise-api-ref/status-settings.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Status and Settings REST API +title: Status and settings REST API published: true -tags: [reference, enterprise, REST, API, reporting, status, URI, ldap, settings] --- REST API for managing settings, checking hub status. @@ -66,7 +65,7 @@ REST API for managing settings, checking hub status. * **license.licenseType** License description. -**Example usage:** `Checking Status` +**Example usage:** `Checking status` ## Get settings @@ -154,4 +153,4 @@ administrator. } ``` -**Example usage:** `Example: Configuring LDAP`, `Example: Changing The Log Level` +**Example usage:** `Example: Configuring LDAP`, `Example: Changing the log level` diff --git a/api/enterprise-api-ref/users-rbac.markdown b/api/enterprise-api-ref/users-rbac.markdown index 68cf07319..19aaec8ea 100644 --- a/api/enterprise-api-ref/users-rbac.markdown +++ b/api/enterprise-api-ref/users-rbac.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Users and Access-Control REST API +title: Users and access-control REST API published: true -tags: [reference, enterprise, REST, API, reporting, URI, users, rbac] --- This REST API allows to manage users allowed to use Mission Portal as also Role Based Access Control settings. @@ -76,7 +75,7 @@ API call allowed only for administrator. * **external** Is user from external source (LDAP/AD). -**Example usage:** `Example: Listing Users` +**Example usage:** `Example: Listing users` ## Get user data @@ -125,7 +124,7 @@ API call allowed only for administrator. * **time_zone** Time zone -**Example usage:** `Example: Retrieving a User` +**Example usage:** `Example: Retrieving a user` ## Create new user @@ -160,7 +159,7 @@ API call allowed only for administrator. } ``` -**Example usage:** `Example: Creating a New User` +**Example usage:** `Example: Creating a new user` ## Update user @@ -195,7 +194,7 @@ API call allowed only for administrator. } ``` -**Example usage:** `Example: Updating an Existing User`, `Example: Adding a User to a Role` +**Example usage:** `Example: Updating an existing user`, `Example: Adding a user to a role` ## Delete user @@ -206,7 +205,7 @@ API call allowed only for administrator. Remove internal user. API call allowed only for administrator. -**Example usage:** `Example: Deleting a User` +**Example usage:** `Example: Deleting a user` ## List RBAC roles diff --git a/api/enterprise-api-ref/vcs-settings.markdown b/api/enterprise-api-ref/vcs-settings.markdown index e27879fe3..7b2f748d6 100644 --- a/api/enterprise-api-ref/vcs-settings.markdown +++ b/api/enterprise-api-ref/vcs-settings.markdown @@ -2,7 +2,6 @@ layout: default title: VCS settings API published: true -tags: [reference, enterprise, API, settings, VCS] --- VCS API for managing version control repository settings. @@ -35,6 +34,7 @@ curl -k --user : \ "data": { "GIT_URL": "https://github.com/cfengine/masterfiles.git", "GIT_REFSPEC": "master", + "PROJECT_SUBDIRECTORY": "path/to/policies", "GIT_USERNAME": "username", "GIT_PASSWORD": "passwordOrToken", "GIT_WORKING_BRANCH": "CF_WORKING_BRANCH", @@ -59,6 +59,9 @@ curl -k --user : \ Git repository URL `Emp: https://github.com/cfengine/masterfiles.git`. Required parameter. * **gitRefspec** *(string)* The Git refspec to checkout. It can be a branch name, a tag name, a commit hash or a partial hash. Required parameter. +* **projectSubdirectory** *(string)* + Subdirectory inside Git repository where the project is located. + Optional parameter. * **gitUsername** *(string)* Git username for authentication, not needed for public repositories. * **gitPassword** *(string)* @@ -76,6 +79,7 @@ curl -k --user : \ -d '{ "gitServer":"https://github.com/cfengine/masterfiles.git", "gitRefspec":"master", + "projectSubdirectory":"", "gitUsername":"gituser", "gitPassword":"passwordOrToken", "gitPrivateKey" "Private key raw content" @@ -89,6 +93,7 @@ curl -k --user : \ { "gitServer": "https://github.com/cfengine/masterfiles.git", "gitRefspec": "master", + "projectSubdirectory": "", "gitUsername": "gituser", "gitPassword": "passwordOrToken", "gitPrivateKey": "/opt/cfengine/userworkdir/admin/.ssh/id_rsa.pvt" @@ -98,3 +103,4 @@ curl -k --user : \ ## History * `vscType` parameter added in 3.19.0, 3.18.1 +* `projectSubdirectory` parameter added in 3.21.7, 3.24.2, 3.26.0 diff --git a/api/enterprise-api-ref/web-rbac.markdown b/api/enterprise-api-ref/web-rbac.markdown index 08a375942..a1d1b62d9 100644 --- a/api/enterprise-api-ref/web-rbac.markdown +++ b/api/enterprise-api-ref/web-rbac.markdown @@ -2,7 +2,6 @@ layout: default title: Web RBAC API published: true -tags: [reference, enterprise, API, settings, RBAC] --- Web RBAC API for managing role based access control settings. diff --git a/cheatsheet.markdown b/cheatsheet.markdown index 8bdc9f6e6..372d2d174 100644 --- a/cheatsheet.markdown +++ b/cheatsheet.markdown @@ -1,6 +1,6 @@ --- layout: printable -title: Markdown Cheatsheet +title: Markdown cheatsheet published: true sorting: 1 alias: markdown-cheatsheet.html @@ -14,7 +14,7 @@ to make it even simpler. Here's a list of the most commonly used formats. * **"Always pull never push"** -## Basic Formatting +## Basic formatting ``` One @@ -52,14 +52,17 @@ For example, On the [functions][Functions] page we can link to the [collecting f Sometimes (because `¯\_(ツ)_/¯`, maybe the page linked to hasn't been parsed yet) a page may not be automatically known. In this case an entry in [_references.md](https://github.com/cfengine/documentation/blob/master/generator/_references.md). -##### Special Characters in link targets +##### Special characters in link targets + +See generator/_scripts/cfdoc_linkresolver.py for how various characters are changed to dashes (--, ,:,.,(,)) and erased ("). +Dashes are removed from the beginning and end of links as well. _Most_ (`¯\_(ツ)_/¯`) special characters are _okay_. For example: * Link targets with `/` (forward slashes) work - * ```[Export/Import][Settings#Export/Import]``` == [Export/Import][Settings#Export/Import] + * ```[Export/import][Settings#Export/import]``` == [Export/import][Settings#Export/import] -Anchors with _underscores_ are problematic, they need to be escaped. +Anchors with _underscores_ are problematic, *may* need to be escaped. For example ```services_autorun``` in the MPF documentation the underscore needs to be escaped with a ```\```. @@ -69,6 +72,16 @@ For example ```services_autorun``` in the MPF documentation the underscore needs **See also:** [`services_autorun` in the Masterfiles Policy Framework][Masterfiles Policy Framework#services\_autorun] +But not always! For example + +``` +**See also:** [cf_lock.lmdb][CFEngine directory structure#state/cf_lock.lmdb] +``` + +**See also:** [cf_lock.lmdb][CFEngine directory structure#state/cf_lock.lmdb] + +Backticks are problematic. It seems impossible to link to anchors that contain backticks. + ### Link to CFEngine keyword The documentation pre-processor will create those automatically. @@ -87,7 +100,7 @@ However, the preprocess will not create links if the code word is in triple back No links: ```classes``` and ```readfile()``` -### Link to External URL +### Link to external URL `[Markdown Documentation](http://daringfireball.net/projects/markdown/)` @@ -208,7 +221,77 @@ however this does not support syntax highlighting and triple backticks are prefe To turn on syntax highlighting, specify the language ("brush") directly after the opening three backticks. Syntax highlighting is provided by pygments. Find all available lexers [here](http://pygments.org/docs/lexers/). -#### CFEngine Code Blocks +#### Command code blocks + +```command +python3 -v +``` + +This code block will have `command` in the header and corresponding icon. + +#### Command code block with output + +To have a component that shows command, and it's output you need to place output code block following command one. + +```command +uname +``` +```output +Linux +``` + +You might also specify output syntax highlighting by adding language +after the starting backticks and placing `[output]` in the first line. +This line won't be shown in the resulted HTML. + +```command +curl --user admin:admin https://test.cfengine.com/api/user +``` + +```json +[output] +{ + "meta": { + "page": 1, + "count": 1, + "total": 1, + "timestamp": 1350994249d + }, + "data": [ + { + "id": "calvin", + "external": true, + "roles": [ + "Huguenots", "Marketing" + ] + } + ] +} +``` + +These two blocks will be joined into one element on the UI. + +#### File code block + +You can specify file name of the code block by adding `[file=Name of the file]` in the first line. +This line won't be shown in the resulting HTML (it will be converted to the heading / frame). + +```cf3 +[file=policy.cf] +bundle agent hello_world +{ + meta: + "tags" + slist => { "autorun" }; + vars: + "github_path" + string => "/tmp/github.com"; +} +``` + +The resulting code block will show `policy.cf` as the filename. + +#### CFEngine code blocks If you want CFEngine syntax highlighting, use @@ -231,7 +314,7 @@ bundle agent example() Other frequently used syntax highlighters shown below. -#### Bash Script Code Blocks +#### Bash script code blocks ```bash #!/bin/bash @@ -251,7 +334,7 @@ do done ``` -#### Console Blocks +#### Console blocks ```console root@policy_server # /etc/init.d/cfengine3 stop @@ -261,7 +344,7 @@ done root@policy_server # /etc/init.d/cfengine3 stop ``` -#### SQL Code Blocks +#### SQL code blocks ```sql SELECT @@ -293,7 +376,7 @@ SELECT ChangeCount DESC ``` -#### Diff Code Blocks +#### Diff code blocks ```diff diff --git a/README.md b/README.md @@ -302,7 +385,7 @@ SELECT +++ b/README.md @@ -377,8 +377,12 @@ As a general note, avoiding abbreviations provides better readability. - * follow the [Policy Style Guide](guide/writing-and-serving-policy/policy-style.markdown) + * follow the [Policy style guide](guide/writing-and-serving-policy/policy-style.markdown) in examples and code snippets -* always run it through Pygments plus the appropriate lexer (only cf3 - supported for now) @@ -323,7 +406,7 @@ index 92555a2..b49c0bb 100644 +++ b/README.md @@ -377,8 +377,12 @@ As a general note, avoiding abbreviations provides better readability. - * follow the [Policy Style Guide](guide/writing-and-serving-policy/policy-style.markdown) + * follow the [Policy style guide](guide/writing-and-serving-policy/policy-style.markdown) in examples and code snippets -* always run it through Pygments plus the appropriate lexer (only cf3 - supported for now) @@ -338,7 +421,7 @@ index 92555a2..b49c0bb 100644 ``` -#### JSON Code Blocks +#### JSON code blocks {% raw %} ```json @@ -378,7 +461,7 @@ index 92555a2..b49c0bb 100644 - "any" ``` -### Code Blocks and Lists +### Code blocks and lists If you want to include a code block within a list, put two tabs (8 spaces) in front of the entire block (4 to make the paragraph part of the list item, and 4 for it a code block): @@ -434,7 +517,7 @@ You can also use backticks (and get syntax highlighting) - just make sure the ba `# Level 1` -# CFEngine Extensions +# CFEngine extensions ## Example policy from core Examples from cfengine/core can be rendered using the `CFEngine_include_example` macro. @@ -482,7 +565,7 @@ Sometimes it's nice to include a snippet from another file. For example, we dyna ***** -## Including External Files +## Including external files Sometimes it's nice to include an external file @@ -542,7 +625,7 @@ If you are referring to something within UI / screenshots / buttons etc use bold -## Self Documenting Policy +## Self documenting policy ### For the stdlib: [%CFEngine_library_include(lib/commands)%] diff --git a/enterprise-cfengine-guide.markdown b/enterprise-cfengine-guide.markdown index cd5d057ef..d95dd359a 100644 --- a/enterprise-cfengine-guide.markdown +++ b/enterprise-cfengine-guide.markdown @@ -7,27 +7,27 @@ sorting: 3 CFEngine Enterprise is an IT automation platform that uses a model-based approach to manage your infrastructure, and applications at WebScale while providing best-in-class scalability, security, enterprise-wide visibility and control. -## WebScale IT Automation ## +## Webscale IT automation ## CFEngine Enterprise provides a secure and stable platform for building and managing both physical and virtual infrastructure. Its distributed architecture, minimal dependencies, and lightweight autonomous agents enable you to manage 5,000 nodes from a single policy server. WebScale does not just imply large server deployments. The speed at which changes are conceived and committed across infrastructure and applications is equally important. Due to execution times measurable in seconds, and one of the most efficient verification mechanisms, CFEngine reduces exposure to unwarranted changes, and prevents extreme delays for planned changes that need to be applied urgently at scale. -## Intelligent Automation of Infrastructure ## +## Intelligent automation of infrastructure ## Automate your infrastructure with self-service capabilities. CFEngine Enterprise enables you to take advantage of agile, secure, and scalable infrastructure automation that makes repairs using a policy-based approach. -## Policy-Based Application Deployment ## +## Policy-based application deployment ## Achieve repeatable, error-free and automated deployment of middleware and application components to a datacenter or cloud-based infrastructure. Along with infrastructure, automated application deployment provides a standardized platform. -## Self-Healing Continuous Operations ## +## Self-healing continuous operations ## Gain visibility into your infrastructure and applications, and be alerted to issues immediately. CFEngine Enterprise contains built-in inventory and reporting modules that automate troubleshooting and compliance checks, as well as remediate in a self-healing fashion. -## CFEngine Enterprise Features ## +## CFEngine Enterprise features ## -### User Interface ### +### User interface ### The CFEngine Enterprise Mission Portal provides a central dashboard for real-time monitoring, search, and reporting for immediate visibility into your environment's actual vs desired state. You can also use Mission Portal to set individual and group alerts and track system events that make you aware of specific infrastructure changes. @@ -37,11 +37,11 @@ The CFEngine Enterprise Mission Portal provides a central dashboard for real-tim CFEngine Enterprise has a simple distributed architecture that scales with minimal resource consumption. Its pull-based system eliminates the need for server-side processing, which means that a single policy server can concurrently serve up to 5,000 nodes doing 5 minute runs with minimal hardware requirements. -### Configurable Data Feeds ### +### Configurable data feeds ### The CFEngine Enterprise `Mission Portal` provides System Administrators and Infrastructure Engineers with detailed information about the actual state of the IT infrastructure and how that compares with the desired state. -### Federation and SQL Reporting ### +### Federation and SQL reporting ### CFEngine Enterprise has the ability to create federated structures, in which parts of organizations can have their own configuration policies, while at the same time the central IT organization may impose some policies that are more global in nature. diff --git a/enterprise-cfengine-guide/install-get-started.markdown b/enterprise-cfengine-guide/install-get-started.markdown index c9125e65b..a0e79361f 100644 --- a/enterprise-cfengine-guide/install-get-started.markdown +++ b/enterprise-cfengine-guide/install-get-started.markdown @@ -1,6 +1,6 @@ --- layout: default -title: Install and Get Started +title: Install and get started published: false sorting: 10 --- @@ -12,21 +12,21 @@ https://docs.google.com/document/d/1CeRR8cuMtrrr0X27gzVzP2ndiU0HuHvo7dJT2vIWfp0/ * [Installation][Install and Get Started#Installation] -* [Post-Install Configuration][Install and Get Started#Post-Install Configuration] +* [Post-install configuration][Install and Get Started#Post-install configuration] ## Installation ## -The [General Installation][General Installation] instructions provide the detailed steps for installing CFEngine, which are generally the same steps to follow for CFEngine Enterprise, with the exception of license keys (if applicable), and also some aspects of post-installation and configuration. +The [General installation][General installation] instructions provide the detailed steps for installing CFEngine, which are generally the same steps to follow for CFEngine Enterprise, with the exception of license keys (if applicable), and also some aspects of post-installation and configuration. -### Installing Enterprise Licenses ### +### Installing Enterprise licenses ### Before you begin, you should have your license key, unless you only plan to use the free 25 node license. The installation instructions will be provided with the key. -## Post-Install Configuration ## +## Post-install configuration ## -### Change Email Setup After CFEngine Enterprise Installation ### +### Change email setup after CFEngine Enterprise installation ### For Enterprise 3.6 local mail relay is used, and it is assumed the server has a proper mail setup. @@ -36,7 +36,7 @@ The default FROM email for all emails sent from the Mission Portal is ```admin@o Consider enabling the built-in version control of your policies as described in -[Version Control and Configuration Policy][Best Practices#Version Control and Configuration Policy] +[Version control and configuration policy][Best practices#Version control and configuration policy] Whether you do or not, please put your policies in some kind of backed-up VCS. Losing work because of "fat fingering" `rm` commands is diff --git a/examples.markdown b/examples.markdown index b59aeab6c..4aa85ac87 100644 --- a/examples.markdown +++ b/examples.markdown @@ -1,33 +1,29 @@ --- layout: default -title: Examples and Tutorials +title: Examples and tutorials published: true sorting: 60 -tags: [Examples] --- -## Links to Examples ## +## Links to examples ## -* [Example Snippets][Example Snippets]: This section is divided into topical areas and includes many examples of policy and promises. Each of the snippets can be easily copied or downloaded to a policy server and used as is. +* [Example snippets][Example snippets]: This section is divided into topical areas and includes many examples of policy and promises. Each of the snippets can be easily copied or downloaded to a policy server and used as is. -Note: CFEngine also includes a small set of examples by default, which can be -found in `/var/cfengine/share/doc/examples`. +**Note:** CFEngine also includes a small set of examples by default, which can be found in `/var/cfengine/share/doc/examples`. -* [Enterprise API Examples][Enterprise API Examples] +* [Enterprise API examples][Enterprise API examples] * [Tutorials][Tutorials] -See Also: +See also: -* [Tutorial for Running Examples][Examples and Tutorials#Tutorial for Running Examples] - * ["Hello World" Policy Example][Examples and Tutorials#"Hello World" Policy Example] - * [Activate a Bundle Manually][Examples and Tutorials#Activate a Bundle Manually] - * [Make the Example Stand Alone][Examples and Tutorials#Make the Example Stand Alone] - * [Make the Example an Executable Script][Examples and Tutorials#Make the Example an Executable Script] - * [Integrating the Example into your Main Policy][Examples and Tutorials#Integrating the Example into your Main Policy] - - -## Tutorial for Running Examples ## +* [Tutorial for running examples][Examples and tutorials#Tutorial for running examples] + * ["Hello world" policy example][Examples and tutorials#"Hello world" policy example] + * [Activate a bundle manually][Examples and tutorials#Activate a bundle manually] + * [Make the example stand alone][Examples and tutorials#Make the example stand alone] + * [Make the example an executable script][Examples and tutorials#Make the example an executable script] + * [Integrating the example into your main policy][Examples and tutorials#Integrating the example into your main policy] +## Tutorial for running examples In this tutorial, you will perform the following: @@ -36,9 +32,9 @@ In this tutorial, you will perform the following: * Make the example an executable script * Add the example to the main policy file (`promises.cf`) -**Note** if your CFEngine administrator has enabled continuous deployment of the policy from a Version Control System, your changes may be overwritten! +**Note** if your CFEngine administrator has enabled continuous deployment of the policy from a Version control System, your changes may be overwritten! -### "Hello World" Policy Example ### +### "Hello world" policy example Policies contain **bundles**, which are collections of promises. A **promise** is a declaration of intent. Bundles allow related promises to be grouped together, as illustrated in the steps that follow. @@ -50,19 +46,15 @@ Following these steps, you will login to your policy server via the SSH protocol 3. To get to the __masterfiles__ directory, type ```cd /var/cfengine/masterfiles```. 4. Create the file with the command: ```vi hello_world.cf ``` 5. In the vi editor, enter ```i``` for "Insert" and enter the following content (ie. copy and paste from a text editor): - - ```cf3 - bundle agent hello_world - { - reports: - - any:: - - "Hello World!"; - - } - ``` - + ```cf3 + [file=hello_world.cf] + bundle agent hello_world + { + reports: + any:: + "Hello World!"; + } + ``` 6. Exit the "Insert" mode by pressing the "esc" button. This will return to the command prompt. 7. Save the changes to the file by typing ```:w``` then "Enter". 8. Exit vi by typing ```:q``` then "Enter". @@ -70,46 +62,42 @@ Following these steps, you will login to your policy server via the SSH protocol In the policy file above, we have defined an **agent bundle** named `hello_world`. Agent bundles are only evaluated by **cf-agent**, the [agent component][cf-agent] of CFEngine. -This bundle [promises][Promise Types] to [report][reports] on any [class of -hosts][Classes and Decisions]. - +This bundle [promises][Promise types] to [report][reports] on any [class of hosts][Classes and decisions]. - -### Activate a Bundle Manually ### +### Activate a bundle manually Activate the bundle manually by executing the following command at prompt: -```console +```command /var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf --bundlesequence hello_world ``` -This command instructs CFEngine to ignore [locks][Controlling Frequency], load +This command instructs CFEngine to ignore [locks][Controlling frequency], load the `hello_world.cf` policy, and activate the `hello_world` bundle. See the output below: -```console -# /var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf --bundlesequence hello_world +```command +/var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf --bundlesequence hello_world +``` +```output 2013-08-20T14:03:43-0500 notice: R: Hello World! ``` As you get familiar with CFEngine, you'll probably start shortening this command to this equivalent: -```console +```command /var/cfengine/bin/cf-agent -Kf ./hello_world.cf -b hello_world ``` - -Note the full path to the binary in the above command. CFEngine stores its binaries in /var/cfengine/bin +Note the full path to the binary in the above command. CFEngine stores its binaries in `/var/cfengine/bin` on Linux and Unix systems. Your path might vary depending on your platform and the packages your are using. CFEngine uses /var because it is one of the Unix file systems that resides locally. Thus, CFEngine can function even if everything else fails (your other file systems, your network, and even system binaries) and possibly repair problems. - - -### Make the Example Stand Alone ### +### Make the example stand alone Instead of specifying the bundle sequence on the command line (as it was above), a [body common -control][Components#Common Control] section can be added to +control][Components#Common control] section can be added to the policy file. The **body common control** refers to those promises that are hard-coded into all CFEngine components and therefore affect the behavior of all components. Note that only one `body common control` is allowed per agent activation. @@ -119,6 +107,7 @@ Go back into vi by typing "vi" at the prompt. Then type ```i``` to insert shown in the following example: ```cf3 +[file=hello_world.cf] body common control { bundlesequence => { "hello_world" }; @@ -127,11 +116,8 @@ body common control bundle agent hello_world { reports: - any:: - "Hello World!"; - } ``` @@ -139,28 +125,28 @@ Now press "esc" to exit the "Insert" mode, then type ```:w``` to save the file c Exit vi by typing ```:q``` then "Enter." This will return to the prompt. Execute the following command: -```console + +```command /var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf ``` - -The output is shown below: - -```console -# /var/cfengine/bin/cf-agent --no-lock --file ./hello_world.cf -2013-08-20T14:25:36-0500 notice: R: Hello World! +```output +notice: R: Hello World! ``` -Note: It may be necessary to add a reference to the standard library within the body common control section, and remove the bundlesequence line. Example: +**Note:** It may be necessary to add a reference to the standard library within the body common control section, and remove the `bundlesequence` line. +Example: ```cf3 -body common control { - inputs => { - "libraries/cfengine_stdlib.cf", - }; +[file=hello_world.cf] +body common control +{ + inputs => { + "libraries/cfengine_stdlib.cf", + }; } ``` -### Make the Example an Executable Script ### +### Make the example an executable script Add the ```#!``` marker ("shebang") to `hello_world.cf` in order to invoke CFEngine policy as an executable script: Again type "vi" then "Enter" then ```i``` to insert the following: @@ -172,6 +158,7 @@ Again type "vi" then "Enter" then ```i``` to insert the following: Add it before __body common control__, as shown below: ```cf3 +[file=hello_world.cf] #!/var/cfengine/bin/cf-agent --no-lock body common control { @@ -181,39 +168,31 @@ body common control bundle agent hello_world { reports: - any:: - "Hello World!"; - } ``` Now exit "Insert" mode by pressing "esc". Save file changes by typing ```:w``` then "Enter" then exit vi by typing ```:q``` then "Enter". This will return to the prompt. -Make the policy file executable, and then run it, by typing the following two commands: +Make the policy file executable: -```console +```command chmod +x ./hello_world.cf ``` -Followed by: +And it can now be run directly: -```console +```command ./hello_world.cf ``` - -See the output below: - -```console -# chmod +x ./hello_world.cf -# ./hello_world.cf +```output 2013-08-20T14:39:34-0500 notice: R: Hello World! ``` -### Integrating the Example into your Main Policy ### +### Integrating the example into your main policy Make the example policy part of your main policy by doing the following on your policy server: diff --git a/examples/example-snippets.markdown b/examples/example-snippets.markdown index 32b1bc85a..2525d2b92 100644 --- a/examples/example-snippets.markdown +++ b/examples/example-snippets.markdown @@ -1,23 +1,22 @@ --- layout: default -title: Example Snippets +title: Example snippets sorting: 1 published: true -tags: [examples, policy, example snippets] --- -* [General Examples][General Examples] -* [Administration Examples][Administration Examples] -* [Measuring Examples][Measuring Examples] -* [Software Administration Examples][Software Administration Examples] -* [Commands, Scripts, and Execution Examples][Commands, Scripts, and Execution Examples] -* [File and Directory Examples][File and Directory Examples] -* [File Template Examples][File Template Examples] -* [Database Examples][Database Examples] -* [Network Examples][Network Examples] -* [System Security Examples][System Security Examples] -* [System Information Examples][System Information Examples] -* [System Administration Examples][System Administration Examples] -* [System File Examples][System File Examples] -* [Windows Registry Examples][Windows Registry Examples] -* [User Management][User Management Examples] +* [General examples][General examples] +* [Administration examples][Administration examples] +* [Measuring examples][Measuring examples] +* [Software administration examples][Software administration examples] +* [Commands, scripts, and execution examples][Commands, scripts, and execution examples] +* [File and directory examples][File and directory examples] +* [File template examples][File template examples] +* [Database examples][Database examples] +* [Network examples][Network examples] +* [System security examples][System security examples] +* [System information examples][System information examples] +* [System administration examples][System administration examples] +* [System file examples][System file examples] +* [Windows registry examples][Windows registry examples] +* [User management][User management examples] diff --git a/examples/example-snippets/active_directory.markdown b/examples/example-snippets/active_directory.markdown index f3df46dcb..b1f137aef 100644 --- a/examples/example-snippets/active_directory.markdown +++ b/examples/example-snippets/active_directory.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Interacting with Directory Services +title: Interacting with directory services published: true sorting: 7 -tags: [Examples, Active Directory, LDAP, ldaparray(), ldaplist() ] --- ## Active directory example diff --git a/examples/example-snippets/basic-file-directory.markdown b/examples/example-snippets/basic-file-directory.markdown index 9d454f571..e5a89d0c7 100644 --- a/examples/example-snippets/basic-file-directory.markdown +++ b/examples/example-snippets/basic-file-directory.markdown @@ -1,36 +1,35 @@ --- layout: default -title: File and Directory Examples +title: File and directory examples published: true sorting: 6 -tags: [Examples,Files,Directories] --- -* [Create files and directories][File and Directory Examples#Create files and directories] -* [Copy single files][File and Directory Examples#Copy single files] -* [Copy directory trees][File and Directory Examples#Copy directory trees] -* [Disabling and rotating files][File and Directory Examples#Disabling and rotating files] -* [Add lines to a file][File and Directory Examples#Add lines to a file] -* [Check file or directory permissions][File and Directory Examples#Check file or directory permissions] -* [Commenting lines in a file][File and Directory Examples#Commenting lines in a file] -* [Copy files][File and Directory Examples#Copy files] -* [Copy and flatten directory][File and Directory Examples#Copy and flatten directory] -* [Copy then edit a file convergently][File and Directory Examples#Copy then edit a file convergently] -* [Deleting lines from a file][File and Directory Examples#Deleting lines from a file] -* [Deleting lines exception][File and Directory Examples#Deleting lines exception] -* [Delete files recursively][File and Directory Examples#Delete files recursively] -* [Editing files][File and Directory Examples#Editing files] -* [Editing tabular files][File and Directory Examples#Editing tabular files] -* [Inserting lines in a file][File and Directory Examples#Inserting lines in a file] -* [Back references in filenames][File and Directory Examples#Back references in filenames] -* [Add variable definitions to a file][File and Directory Examples#Add variable definitions to a file] -* [Linking files][File and Directory Examples#Linking files] -* [Listing files-pattern in a directory][File and Directory Examples#Listing files-pattern in a directory] -* [Locate and transform files][File and Directory Examples#Locate and transform files] -* [BSD flags][File and Directory Examples#BSD flags] -* [Search and replace text][File and Directory Examples#Search and replace text] -* [Selecting a region in a file][File and Directory Examples#Selecting a region in a file] -* [Warn if matching line in file][File and Directory Examples#Warn if matching line in file] +* [Create files and directories][File and directory examples#Create files and directories] +* [Copy single files][File and directory examples#Copy single files] +* [Copy directory trees][File and directory examples#Copy directory trees] +* [Disabling and rotating files][File and directory examples#Disabling and rotating files] +* [Add lines to a file][File and directory examples#Add lines to a file] +* [Check file or directory permissions][File and directory examples#Check file or directory permissions] +* [Commenting lines in a file][File and directory examples#Commenting lines in a file] +* [Copy files][File and directory examples#Copy files] +* [Copy and flatten directory][File and directory examples#Copy and flatten directory] +* [Copy then edit a file convergently][File and directory examples#Copy then edit a file convergently] +* [Deleting lines from a file][File and directory examples#Deleting lines from a file] +* [Deleting lines exception][File and directory examples#Deleting lines exception] +* [Delete files recursively][File and directory examples#Delete files recursively] +* [Editing files][File and directory examples#Editing files] +* [Editing tabular files][File and directory examples#Editing tabular files] +* [Inserting lines in a file][File and directory examples#Inserting lines in a file] +* [Back references in filenames][File and directory examples#Back references in filenames] +* [Add variable definitions to a file][File and directory examples#Add variable definitions to a file] +* [Linking files][File and directory examples#Linking files] +* [Listing files-pattern in a directory][File and directory examples#Listing files-pattern in a directory] +* [Locate and transform files][File and directory examples#Locate and transform files] +* [BSD flags][File and directory examples#BSD flags] +* [Search and replace text][File and directory examples#Search and replace text] +* [Selecting a region in a file][File and directory examples#Selecting a region in a file] +* [Warn if matching line in file][File and directory examples#Warn if matching line in file] ## Create files and directories ## diff --git a/examples/example-snippets/cfengine-administration.markdown b/examples/example-snippets/cfengine-administration.markdown index bb7b0f1ba..352761f0c 100644 --- a/examples/example-snippets/cfengine-administration.markdown +++ b/examples/example-snippets/cfengine-administration.markdown @@ -1,13 +1,12 @@ --- layout: default -title: Administration Examples +title: Administration examples published: true sorting: 2 -tags: [Examples, CFEngine Administration] --- -* [Ordering promises][Administration Examples#Ordering promises] -* [Aborting execution][Administration Examples#Aborting execution] +* [Ordering promises][Administration examples#Ordering promises] +* [Aborting execution][Administration examples#Aborting execution] ## Ordering promises diff --git a/examples/example-snippets/commands-scripts-execution.markdown b/examples/example-snippets/commands-scripts-execution.markdown index 472f7d71c..51fae2210 100644 --- a/examples/example-snippets/commands-scripts-execution.markdown +++ b/examples/example-snippets/commands-scripts-execution.markdown @@ -1,18 +1,17 @@ --- layout: default -title: Commands, Scripts, and Execution Examples +title: Commands, scripts, and execution examples published: true sorting: 5 -tags: [Examples,Commands,Scripts] --- -* [Command or script execution][Commands, Scripts, and Execution Examples#Command or script execution] -* [Change directory for command][Commands, Scripts, and Execution Examples#Change directory for command] -* [Commands example][Commands, Scripts, and Execution Examples#Commands example] -* [Execresult example][Commands, Scripts, and Execution Examples#Execresult example] -* [Methods][Commands, Scripts, and Execution Examples#Methods] -* [Method validation][Commands, Scripts, and Execution Examples#Method validation] -* [Trigger classes][Commands, Scripts, and Execution Examples#Trigger classes] +* [Command or script execution][Commands, scripts, and execution examples#Command or script execution] +* [Change directory for command][Commands, scripts, and execution examples#Change directory for command] +* [Commands example][Commands, scripts, and execution examples#Commands example] +* [Execresult example][Commands, scripts, and execution examples#Execresult example] +* [Methods][Commands, scripts, and execution examples#Methods] +* [Method validation][Commands, scripts, and execution examples#Method validation] +* [Trigger classes][Commands, scripts, and execution examples#Trigger classes] ## Command or script execution ## diff --git a/examples/example-snippets/database.markdown b/examples/example-snippets/database.markdown index e6eae4b49..a138adfd8 100644 --- a/examples/example-snippets/database.markdown +++ b/examples/example-snippets/database.markdown @@ -1,12 +1,11 @@ --- layout: default -title: Database Examples +title: Database examples published: true sorting: 8 -tags: [Examples,Databases] --- -* [Database creation][Database Examples#Database creation] +* [Database creation][Database examples#Database creation] ## Database creation diff --git a/examples/example-snippets/file-template.markdown b/examples/example-snippets/file-template.markdown index accf824e2..35ea1ae4a 100644 --- a/examples/example-snippets/file-template.markdown +++ b/examples/example-snippets/file-template.markdown @@ -1,16 +1,15 @@ --- layout: default -title: File Template Examples +title: File template examples published: true sorting: 7 -tags: [Examples] --- -* [Templating][File Template Examples#Templating] +* [Templating][File template examples#Templating] ## Templating -With CFEngine you have a choice between editing `deltas' into files or distributing more-or-less finished templates. Which method you should choose depends should be made by whatever is easiest. +With CFEngine you have a choice between editing _deltas_ into files or distributing more-or-less finished templates. Which method you should choose depends should be made by whatever is easiest. If you are managing only part of the file, and something else (e.g. a package manager) is managing most of it, then it makes sense to use CFEngine file editing. If you are managing everything in the file, then it makes sense to make the edits by hand and install them using CFEngine. You can use variables within source text files and let CFEngine expand them locally in situ, so that you can make generic templates that apply netwide. @@ -26,6 +25,6 @@ To copy and expand this template, you can use a pattern like this: [%CFEngine_include_snippet(templating_1.cf, .* )%] -The the following driving code (based on `copy then edit') can be placed in a library, after configuring to your environmental locations: +The the following driving code (based on _copy then edit_) can be placed in a library, after configuring to your environmental locations: [%CFEngine_include_snippet(templating_1.cf, .* )%] diff --git a/examples/example-snippets/file_permissions.markdown b/examples/example-snippets/file_permissions.markdown index 180933f4f..be0a012f6 100644 --- a/examples/example-snippets/file_permissions.markdown +++ b/examples/example-snippets/file_permissions.markdown @@ -1,9 +1,8 @@ --- layout: default -title: File Permissions +title: File permissions published: true sorting: 15 -tags: [Examples,File Permissions,Extended ACLs] --- ## ACL file example diff --git a/examples/example-snippets/general.markdown b/examples/example-snippets/general.markdown index b8daf5717..8f55c1ef0 100644 --- a/examples/example-snippets/general.markdown +++ b/examples/example-snippets/general.markdown @@ -1,23 +1,22 @@ --- layout: default -title: General Examples +title: General examples published: true sorting: 1 -tags: [Examples] --- -* [Basic Example][General Examples#Basic Example] -* [Hello world][General Examples#Hello world] -* [Array example][General Examples#Array example] +* [Basic example][General examples#Basic example] +* [Hello world][General examples#Hello world] +* [Array example][General examples#Array example] -## Basic Example ## +## Basic example ## To get started with CFEngine, you can imagine the following template for entering examples. This part of the code is common to all the examples. [%CFEngine_include_snippet(basic_example.cf, .* )%] -# The general pattern +## The general pattern The general pattern of the syntax is like this (colors in html version: red, CFEngine word; blue, user-defined word): @@ -27,7 +26,7 @@ bundle component name(parameters) what_type: where_when:: - # Traditional comment + ## Traditional comment "promiser" -> { "promisee1", "promisee2" }, @@ -38,11 +37,11 @@ what_type: } ``` -## Hello world +### Hello world [%CFEngine_include_snippet(hello_world.cf, .* )%] -## Array example ## +### Array example [%CFEngine_include_snippet(array_example.cf, .* )%] diff --git a/examples/example-snippets/network.markdown b/examples/example-snippets/network.markdown index 9322380d9..d9106d578 100644 --- a/examples/example-snippets/network.markdown +++ b/examples/example-snippets/network.markdown @@ -1,18 +1,17 @@ --- layout: default -title: Network Examples +title: Network examples published: true sorting: 9 -tags: [Examples] --- -* [Find MAC address][Network Examples#Find MAC address] -* [Client-server example][Network Examples#Client-server example] -* [Read from a TCP socket][Network Examples#Read from a TCP socket] -* [Set up a PXE boot server][Network Examples#Set up a PXE boot server] -* [Resolver management][Network Examples#Resolver management] -* [Mount NFS filesystem][Network Examples#Mount NFS filesystem] -* [Unmount NFS filesystem][Network Examples#Unmount NFS filesystem] +* [Find MAC address][Network examples#Find MAC address] +* [Client-server example][Network examples#Client-server example] +* [Read from a TCP socket][Network examples#Read from a TCP socket] +* [Set up a PXE boot server][Network examples#Set up a PXE boot server] +* [Resolver management][Network examples#Resolver management] +* [Mount NFS filesystem][Network examples#Mount NFS filesystem] +* [Unmount NFS filesystem][Network examples#Unmount NFS filesystem] * Find the MAC address * Mount NFS filesystem diff --git a/examples/example-snippets/promise-patterns.markdown b/examples/example-snippets/promise-patterns.markdown index aadc984c1..8a8123373 100644 --- a/examples/example-snippets/promise-patterns.markdown +++ b/examples/example-snippets/promise-patterns.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Common Promise Patterns +title: Common promise patterns sorting: 2 published: true -tags: [examples, policy] --- This section includes includes common promise patterns. Refer to them as you @@ -14,14 +13,14 @@ write policy for your system. * [Check filesystem space][Check filesystem space] * [Copy single files][Copy single files] * [Create files and directories][Create files and directories] -* [Customize Message of the Day][Customize Message of the Day] +* [Customize message of the day][Customize message of the day] * [Distribute ssh keys][Distribute ssh keys] * [Ensure a process is not running][Ensure a process is not running] * [Ensure a service is enabled and running][Ensure a service is enabled and running] * [Find the MAC address][Find the MAC address] * [Install packages][Install packages] * [Mount NFS filesystem][Mount NFS filesystem] -* [Restart a Process][Restart a Process] +* [Restart a process][Restart a process] * [Set up sudo][Set up sudo] * [Set up time management through NTP][Set up time management through NTP] * [Set up name resolution with DNS][Set up name resolution with DNS] diff --git a/examples/example-snippets/promise-patterns/example_aborting_execution.markdown b/examples/example-snippets/promise-patterns/example_aborting_execution.markdown index 2ecbeadd0..315f2e2d0 100644 --- a/examples/example-snippets/promise-patterns/example_aborting_execution.markdown +++ b/examples/example-snippets/promise-patterns/example_aborting_execution.markdown @@ -2,7 +2,6 @@ layout: default title: Aborting execution published: true -tags: [Examples, Policy, aborting execution] reviewed: 2013-05-30 reviewed-by: atsaloli --- @@ -16,17 +15,21 @@ If any of these classes becomes defined, it will cause the current bundle to be This is how the policy runs when the userlist is valid: - # cf-agent -f unit_abort.cf - R: User name mark is valid at 4 letters - R: User name john is valid at 4 letters - # - +```command +cf-agent -f unit_abort.cf +``` +```output +R: User name mark is valid at 4 letters +R: User name john is valid at 4 letters +``` This is how the policy runs when the userlist contains an invalid entry: - # cf-agent -f unit_abort.cf - Bundle example aborted on defined class "invalid" - # - +```command +cf-agent -f unit_abort.cf +``` +```output +Bundle example aborted on defined class "invalid" +``` To run this example file as part of your main policy you need to make an additional change: diff --git a/examples/example-snippets/promise-patterns/example_change_detection.markdown b/examples/example-snippets/promise-patterns/example_change_detection.markdown index 2eae6e871..65e9e9efb 100644 --- a/examples/example-snippets/promise-patterns/example_change_detection.markdown +++ b/examples/example-snippets/promise-patterns/example_change_detection.markdown @@ -2,7 +2,6 @@ layout: default title: Change detection published: true -tags: [Examples, Policy, change detection] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -23,18 +22,22 @@ First, let's create some files for CFEngine to monitor: CFEngine detects new files and adds them to the file integrity database: +```command +cf-agent -f unit_change_detect.cf ``` -# cf-agent -f unit_change_detect.cf +```output 2013-06-06T20:53:26-0700 error: /example/files/'/etc/example': File '/etc/example/example.conf' was not in 'md5' database - new file found -# cf-agent -f unit_change_detect.cf -K +``` + +```command +cf-agent -f unit_change_detect.cf -K ``` If there are no changes, CFEngine runs silently: -``` -# cf-agent -f unit_change_detect.cf -# +```command +cf-agent -f unit_change_detect.cf ``` Now let's update the mtime, and then the mtime and content. diff --git a/examples/example-snippets/promise-patterns/example_copy_single_files.markdown b/examples/example-snippets/promise-patterns/example_copy_single_files.markdown index f16966617..e613df537 100644 --- a/examples/example-snippets/promise-patterns/example_copy_single_files.markdown +++ b/examples/example-snippets/promise-patterns/example_copy_single_files.markdown @@ -2,7 +2,6 @@ layout: default title: Copy single files published: true -tags: [Examples, Policy, copy files] reviewed: 2013-06-08 reviewed-by: atsaloli --- diff --git a/examples/example-snippets/promise-patterns/example_create_filedir.markdown b/examples/example-snippets/promise-patterns/example_create_filedir.markdown index d6537610b..da0c7ef10 100644 --- a/examples/example-snippets/promise-patterns/example_create_filedir.markdown +++ b/examples/example-snippets/promise-patterns/example_create_filedir.markdown @@ -2,7 +2,6 @@ layout: default title: Create files and directories published: true -tags: [Examples, Policy, create, files and directories] --- The following is a standalone policy that will create the file @@ -13,10 +12,11 @@ and set permissions on both. Example output: +```command +cf-agent -f unit_create_filedir.cf -I ``` -# cf-agent -f unit_create_filedir.cf -I +```output 2013-06-08T14:56:26-0700 info: /example/files/'/home/mark/tmp/test_plain': Created file '/home/mark/tmp/test_plain', mode 0640 2013-06-08T14:56:26-0700 info: /example/files/'/home/mark/tmp/test_dir/.': Created directory '/home/mark/tmp/test_dir/.' 2013-06-08T14:56:26-0700 info: /example/files/'/home/mark/tmp/test_dir/.': Object '/home/mark/tmp/test_dir' had permission 0755, changed it to 0750 -# ``` diff --git a/examples/example-snippets/promise-patterns/example_diskfree.markdown b/examples/example-snippets/promise-patterns/example_diskfree.markdown index 7223518a8..f4d8f72ec 100644 --- a/examples/example-snippets/promise-patterns/example_diskfree.markdown +++ b/examples/example-snippets/promise-patterns/example_diskfree.markdown @@ -2,7 +2,6 @@ layout: default title: Check filesystem space published: true -tags: [Examples, Policy, check, filesystem] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -13,11 +12,17 @@ Check how much space (in KB) is available on a directory's current partition. Example output: +```command +cf-agent -f unit_diskfree.cf ``` -# cf-agent -f unit_diskfree.cf +```output R: Freedisk 48694692 -# df -k /tmp +``` + +```command +df -k /tmp +``` +```output Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 149911836 93602068 48694692 66% / -# ``` diff --git a/examples/example-snippets/promise-patterns/example_edit_motd.markdown b/examples/example-snippets/promise-patterns/example_edit_motd.markdown index fc7dc38b9..5bf68cd2a 100644 --- a/examples/example-snippets/promise-patterns/example_edit_motd.markdown +++ b/examples/example-snippets/promise-patterns/example_edit_motd.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Customize Message of the Day +title: Customize message of the day published: true -tags: [Examples, Policy, motd, file editing, files] reviewed: 2015-12-18 reviewed-by: enrico & nick --- @@ -25,12 +24,16 @@ render a `/etc/motd` using a mustache template and add useful information as: The bundle is defined like this: +{%raw%} [%CFEngine_include_example(mustache_template_motd.cf)%] +{%endraw%} **Example run:** -```console -root@debian8:~/core/examples# cf-agent -KIf ./mustache_template_motd.cf; cat /etc/motd +```command +cf-agent -KIf ./mustache_template_motd.cf; cat /etc/motd +``` +```output info: Updated rendering of '/etc/motd' from mustache template 'inline' info: files promise '/etc/motd' repaired # Managed by CFEngine diff --git a/examples/example-snippets/promise-patterns/example_edit_name_resolution.markdown b/examples/example-snippets/promise-patterns/example_edit_name_resolution.markdown index 6bfa3bb15..e5492f70f 100644 --- a/examples/example-snippets/promise-patterns/example_edit_name_resolution.markdown +++ b/examples/example-snippets/promise-patterns/example_edit_name_resolution.markdown @@ -2,7 +2,6 @@ layout: default title: Set up name resolution with DNS published: true -tags: [Examples, Policy, dns, file editing, files] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -12,50 +11,45 @@ There are many ways to configure name resolution. A simple and straightforward a ```cf3 body common control { -bundlesequence => { "edit_name_resolution" }; + bundlesequence => { "edit_name_resolution" }; } bundle agent edit_name_resolution { - -files: - - "/tmp/resolv.conf" # This is for testing, change to "$(sys.resolv)" to put in production - - comment => "Add lines to the resolver configuration", - create => "true", # Make sure the file exists, create it if not - edit_line => resolver, # Call the resolver bundle defined below to do the editing - edit_defaults => empty; # Baseline memory model of file to empty before processing - # bundle edit_line resolver + files: + "/tmp/resolv.conf" # This is for testing, change to "$(sys.resolv)" to put in production + comment => "Add lines to the resolver configuration", + create => "true", # Make sure the file exists, create it if not + edit_line => resolver, # Call the resolver bundle defined below to do the editing + edit_defaults => empty; # Baseline memory model of file to empty before processing + # bundle edit_line resolver } bundle edit_line resolver { - -insert_lines: - - any:: # Class/context where you use the below nameservers. Change to appropriate class - # for your system (if not any::, for example server_group::, ubuntu::, etc.) - - # insert the search domain or name servers we want - "search mydomain.tld" location => start; # Replace mydomain.tld with your domain name - # The search line will always be at the start of the file - "nameserver 128.39.89.8"; - "nameserver 128.39.74.66"; + insert_lines: + any:: + # Class/context where you use the below nameservers. Change to appropriate class + # for your system (if not any::, for example server_group::, ubuntu::, etc.) + # insert the search domain or name servers we want + "search mydomain.tld" + location => start; # Replace mydomain.tld with your domain name + # The search line will always be at the start of the file + "nameserver 128.39.89.8"; + "nameserver 128.39.74.66"; } body edit_defaults empty { -empty_file_before_editing => "true"; + empty_file_before_editing => "true"; } body location start { -before_after => "before"; + before_after => "before"; } ``` - Example run: ``` diff --git a/examples/example-snippets/promise-patterns/example_enable_service.markdown b/examples/example-snippets/promise-patterns/example_enable_service.markdown index a3211af35..083b92cba 100644 --- a/examples/example-snippets/promise-patterns/example_enable_service.markdown +++ b/examples/example-snippets/promise-patterns/example_enable_service.markdown @@ -2,7 +2,6 @@ layout: default title: Ensure a service is enabled and running published: true -tags: [examples, services] reviewed: 2016-06-28 reviewed-by: nickanderson --- @@ -25,8 +24,10 @@ correct return codes for status checks. We can see that before the policy run `sysstat` is *inactive*, `apache2` is *active*, `cups` is *active*, `ssh` is *active* and `cron` is *inactive*. -```console -root@ubuntu:# systemctl is-active sysstat apache2 cups ssh cron +```command +systemctl is-active sysstat apache2 cups ssh cron +``` +```output inactive active active @@ -36,21 +37,25 @@ inactive Now we run the policy to converge the system to the desired state. -```console -root@ubuntu:# cf-agent --no-lock --inform --file ./services.cf - info: Executing 'no timeout' ... '/bin/systemctl --no-ask-password --global --system -q stop apache2' - info: Completed execution of '/bin/systemctl --no-ask-password --global --system -q stop apache2' - info: Executing 'no timeout' ... '/bin/systemctl --no-ask-password --global --system -q stop cups' - info: Completed execution of '/bin/systemctl --no-ask-password --global --system -q stop cups' - info: Executing 'no timeout' ... '/bin/systemctl --no-ask-password --global --system -q start cron' - info: Completed execution of '/bin/systemctl --no-ask-password --global --system -q start cron' +```command +cf-agent --no-lock --inform --file ./services.cf +``` +```output +info: Executing 'no timeout' ... '/bin/systemctl --no-ask-password --global --system -q stop apache2' +info: Completed execution of '/bin/systemctl --no-ask-password --global --system -q stop apache2' +info: Executing 'no timeout' ... '/bin/systemctl --no-ask-password --global --system -q stop cups' +info: Completed execution of '/bin/systemctl --no-ask-password --global --system -q stop cups' +info: Executing 'no timeout' ... '/bin/systemctl --no-ask-password --global --system -q start cron' +info: Completed execution of '/bin/systemctl --no-ask-password --global --system -q start cron' ``` After the policy run we can see that `systat`, `apache2`, and `cups` are *inactive*. `ssh` and `cron` are *active* as specified in the policy. -```console -root@ubuntu:/home/nickanderson/CFEngine/core/examples# systemctl is-active sysstat apache2 cups ssh cron +```command +systemctl is-active sysstat apache2 cups ssh cron +``` +```output inactive inactive inactive @@ -64,52 +69,98 @@ We can see that before the policy run `sysstat` is not reporting status correctly , `httpd` is *running*, `cups` is *running*, `sshd` is *running* and `crond` is *not running*. -```console -[root@localhost examples]# service sysstat status; echo $? +```command +service sysstat status; echo $? +``` +```output 3 -[root@localhost examples]# service httpd status; echo $? +``` + +```command +service httpd status; echo $? +``` +```output httpd (pid 3740) is running... 0 -[root@localhost examples]# service cups status; echo $? +``` + +```command +service cups status; echo $? +``` +```output cupsd (pid 3762) is running... 0 -[root@localhost examples]# service sshd status; echo $? +``` + +```command +service sshd status; echo $? +``` +```output openssh-daemon (pid 3794) is running... 0 -[root@localhost examples]# service crond status; echo $? +``` + +```command +service crond status; echo $? +``` +```output crond is stopped 3 ``` Now we run the policy to converge the system to the desired state. -```console -[root@localhost examples]# cf-agent -KIf ./services.cf - info: Executing 'no timeout' ... '/etc/init.d/crond start' - info: Completed execution of '/etc/init.d/crond start' - info: Executing 'no timeout' ... '/etc/init.d/httpd stop' - info: Completed execution of '/etc/init.d/httpd stop' - info: Executing 'no timeout' ... '/etc/init.d/cups stop' - info: Completed execution of '/etc/init.d/cups stop' +```command +cf-agent -KIf ./services.cf +``` +```output +info: Executing 'no timeout' ... '/etc/init.d/crond start' +info: Completed execution of '/etc/init.d/crond start' +info: Executing 'no timeout' ... '/etc/init.d/httpd stop' +info: Completed execution of '/etc/init.d/httpd stop' +info: Executing 'no timeout' ... '/etc/init.d/cups stop' +info: Completed execution of '/etc/init.d/cups stop' ``` After the policy run we can see that `systat` is still not reporting status correctly (some services do not respond to standard checks), `apache2`, and `cups` are *inactive*. `ssh` and `cron` are *active* as specified in the policy. -```console -[root@localhost examples]# service sysstat status; echo $? +```command +service sysstat status; echo $? +``` +```output 3 -[root@localhost examples]# service httpd status; echo $? +``` + +```command +service httpd status; echo $? +``` +```output httpd is stopped 3 -[root@localhost examples]# service cups status; echo $? -cupsd is stopped +``` + +```command +service cups status; echo $? +``` +```output +cups is stopped 3 -[root@localhost examples]# service sshd status; echo $? +``` + +```command +service sshd status; echo $? +``` +```output openssh-daemon (pid 3794) is running... 0 -[root@localhost examples]# service crond status; echo $? +``` + +```command +service crond status; echo $? +``` +```output crond (pid 3929) is running... 0 ``` diff --git a/examples/example-snippets/promise-patterns/example_find_mac_addr.markdown b/examples/example-snippets/promise-patterns/example_find_mac_addr.markdown index 42d35b908..4dc4b2f82 100644 --- a/examples/example-snippets/promise-patterns/example_find_mac_addr.markdown +++ b/examples/example-snippets/promise-patterns/example_find_mac_addr.markdown @@ -2,7 +2,6 @@ layout: default title: Find the MAC address published: true -tags: [Examples, Policy, MAC address] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -79,10 +78,11 @@ This policy can be found in `/var/cfengine/masterfiles/example_find_mac_addr.cf` Example run: +```command +cf-agent -f example_find_mac_addr.cf ``` -# cf-agent -f example_find_mac_addr.cf +```output 2013-06-08T16:59:19-0700 notice: R: MAC address is a4:ba:db:d7:59:32 -# ``` While the above illustrates the flexiblity of CFEngine in diff --git a/examples/example-snippets/promise-patterns/example_install_package.markdown b/examples/example-snippets/promise-patterns/example_install_package.markdown index aaacfc0b4..251e88be7 100644 --- a/examples/example-snippets/promise-patterns/example_install_package.markdown +++ b/examples/example-snippets/promise-patterns/example_install_package.markdown @@ -2,7 +2,6 @@ layout: default title: Install packages published: true -tags: [Examples, Policy, packages] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -51,16 +50,26 @@ CFEngine downloads the necessary packages from the default repositories if they Example run: +```command +dpkg -r lynx ntp # remove packages so CFEngine has something to repair ``` -# dpkg -r lynx ntp # remove packages so CFEngine has something to repair +```output (Reading database ... 234887 files and directories currently installed.) Removing lynx ... Removing ntp ... * Stopping NTP server ntpd [ OK ] Processing triggers for ureadahead ... Processing triggers for man-db ... -# cf-agent -f install_packages.cf # install packages -# dpkg -l lynx ntp # show installed packages +``` + +```command +cf-agent -f install_packages.cf # install packages +``` + +```command +dpkg -l lynx ntp # show installed packages +``` +```output Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) @@ -68,7 +77,6 @@ Desired=Unknown/Install/Remove/Purge/Hold +++-===============================-====================-====================-==================================================================== ii lynx 2.8.8dev.12-2ubuntu0 all Text-mode WWW Browser (transitional package) ii ntp 1:4.2.6.p3+dfsg-1ubu amd64 Network Time Protocol daemon and utility programs -# ``` There are examples in `/var/cfengine/share/doc/examples/` of installing packages using specific package managers: diff --git a/examples/example-snippets/promise-patterns/example_mount_nfs.markdown b/examples/example-snippets/promise-patterns/example_mount_nfs.markdown index e199a3ee0..2420fb28d 100644 --- a/examples/example-snippets/promise-patterns/example_mount_nfs.markdown +++ b/examples/example-snippets/promise-patterns/example_mount_nfs.markdown @@ -2,7 +2,6 @@ layout: default title: Mount NFS filesystem published: true -tags: [Examples, Policy, mount, nfs, filesystem] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -47,14 +46,25 @@ Here is an example run. At start, the filesystem is not in /etc/fstab and is no Now we run CFEngine to mount the filesystem and add it to /etc/fstab: +```command +cf-agent -f example_mount_nfs.cf ``` -# cf-agent -f example_mount_nfs.cf +```output 2013-06-08T17:48:42-0700 error: Attempting abort because mount went into a retry loop. -# grep mnt /etc/fstab +``` + +```command +grep mnt /etc/fstab +``` +```output fileserver:/home /mnt nfs rw -# df |grep mnt +``` + +```command +df |grep mnt +``` +```output fileserver:/home 149912064 94414848 47882240 67% /mnt -# ``` Note: CFEngine errors out after it mounts the filesystem and updates diff --git a/examples/example-snippets/promise-patterns/example_ntp.markdown b/examples/example-snippets/promise-patterns/example_ntp.markdown index abd5f28fd..484b8df8e 100644 --- a/examples/example-snippets/promise-patterns/example_ntp.markdown +++ b/examples/example-snippets/promise-patterns/example_ntp.markdown @@ -2,7 +2,6 @@ layout: default title: Set up time management through NTP published: true -tags: [Examples, Policy, ntp, file editing] reviewed: 2013-06-09 reviewed-by: atsaloli --- @@ -16,225 +15,180 @@ ntpdate syncs). This example demonstrates you can have a lot of low-level detailed control if you want it. ```cf3 - bundle agent system_time_ntp - { - vars: - - linux:: - - "cache_dir" string => "$(sys.workdir)/cache"; # Cache directory for NTP config files - - "ntp_conf" string => "/etc/ntp.conf"; # Target file for NTP configuration - - "ntp_server" string => "172.16.12.161"; # - "ntp_network" string => "172.16.12.0"; # IP address and netmask of your local NTP server - "ntp_mask" string => "255.255.255.0"; # - - "ntp_pkgs" slist => { "ntp" }; # NTP packages to be installed to ensure service - - - # Define a class for the NTP server - classes: - - any:: - - "ntp_hosts" or => { classmatch(canonify("ipv4_$(ntp_server)")) }; - - - # Ensure that the NTP packages are installed - packages: - - ubuntu:: - - "$(ntp_pkgs)" - - comment => "setup NTP", - package_policy => "add", - package_method => generic; - - - # Ensure existence of file and directory for NTP drift learning statistics - files: - - linux:: - - "/var/lib/ntp/ntp.drift" - - comment => "Enable ntp service", - create => "true"; - - "/var/log/ntpstats/." - - comment => "Create a statistic directory", - perms => mog("644","ntp","ntp"), - create => "true"; - - ntp_hosts:: - - - # Build the cache configuration file for the NTP server - "/var/cfengine/cache/ntp.conf" - - comment => "Build $(this.promiser) cache file for NTP server", - create => "true", - edit_defaults => empty, - edit_line => restore_ntp_master("$(ntp_network)","$(ntp_mask)"); - - centos.ntp_hosts:: - - - # Copy the cached configuration file to its target destination - "$(ntp_conf)" - - comment => "Ensure $(this.promiser) in a perfect condition", - copy_from => local_cp("$(cache_dir)/ntp.conf"), - classes => if_repaired("refresh_ntpd_centos"); - - ubuntu.ntp_hosts:: - - "$(ntp_conf)" - - comment => "Ensure $(this.promiser) in a perfect condition", - copy_from => local_cp("$(cache_dir)/ntp.conf"), - classes => if_repaired("refresh_ntpd_ubuntu"); - - !ntp_hosts:: - - - # Build the cache configuration file for the NTP client - "$(cache_dir)/ntp.conf" - - comment => "Build $(this.promiser) cache file for NTP client", - create => "true", - edit_defaults => empty, - edit_line => restore_ntp_client("$(ntp_server)"); - - centos.!ntp_hosts:: - - - # Copy the cached configuration file to its target destination - "$(ntp_conf)" - - comment => "Ensure $(this.promiser) in a perfect condition", - copy_from => local_cp("$(cache_dir)/ntp.conf"), - classes => if_repaired("refresh_ntpd_centos"); - - ubuntu.!ntp_hosts:: - - "$(ntp_conf)" - - comment => "Ensure $(this.promiser) in a perfect condition", - copy_from => local_cp("$(cache_dir)/ntp.conf"), - classes => if_repaired("refresh_ntpd_ubuntu"); - - - # Set classes (conditions) for to restart the NTP daemon if there have been any changes to configuration - processes: - - centos:: - - "ntpd.*" - - restart_class => "refresh_ntpd_centos"; - - ubuntu:: - - "ntpd.*" - - restart_class => "refresh_ntpd_ubuntu"; - - - # Restart the NTP daemon if the configuration has changed - commands: - - refresh_ntpd_centos:: - - "/etc/init.d/ntpd restart"; - - refresh_ntpd_ubuntu:: - - "/etc/init.d/ntp restart"; - - } - - ####################################################### - - bundle edit_line restore_ntp_master(network,mask) - { - vars: - "list" string => - "###################################### - # ntp.conf-master - - driftfile /var/lib/ntp/ntp.drift - statsdir /var/log/ntpstats/ - - statistics loopstats peerstats clockstats - filegen loopstats file loopstats type day enable - filegen peerstats file peerstats type day enable - filegen clockstats file clockstats type day enable - - # Use public servers from the pool.ntp.org project. - # Please consider joining the pool (http://www.pool.ntp.org/join.html). - # Consider changing the below servers to a location near you for better time - # e.g. server 0.europe.pool.ntp.org, or server 0.no.pool.ntp.org etc. - server 0.centos.pool.ntp.org - server 1.centos.pool.ntp.org - server 2.centos.pool.ntp.org - - # Permit time synchronization with our time source, but do not - # permit the source to query or modify the service on this system. - restrict -4 default kod nomodify notrap nopeer noquery - restrict -6 default kod nomodify notrap nopeer noquery - - # Permit all access over the loopback interface. This could - # be tightened as well, but to do so would effect some of - # the administrative functions. - restrict 127.0.0.1 - restrict ::1 - - # Hosts on local network are less restricted. - restrict $(network) mask $(mask) nomodify notrap"; - - insert_lines: - "$(list)"; - } - - ####################################################### - - bundle edit_line restore_ntp_client(serverip) - { - vars: - "list" string => - "###################################### - # This file is protected by cfengine # - ###################################### - # ntp.conf-client - - driftfile /var/lib/ntp/ntp.drift - statsdir /var/log/ntpstats/ - - statistics loopstats peerstats clockstats - filegen loopstats file loopstats type day enable - filegen peerstats file peerstats type day enable - filegen clockstats file clockstats type day enable - - # Permit time synchronization with our time source, but do not - # permit the source to query or modify the service on this system. - restrict -4 default kod nomodify notrap nopeer noquery - restrict -6 default kod nomodify notrap nopeer noquery - - # Permit all access over the loopback interface. This could - # be tightened as well, but to do so would effect some of - # the administrative functions. - restrict 127.0.0.1 - restrict ::1 - server $(serverip) - restrict $(serverip) nomodify"; - - insert_lines: - "$(list)"; - } +bundle agent system_time_ntp +{ + vars: + linux:: + "cache_dir" + string => "$(sys.workdir)/cache"; # Cache directory for NTP config files + "ntp_conf" + string => "/etc/ntp.conf"; # Target file for NTP configuration + "ntp_server" + string => "172.16.12.161"; + "ntp_network" + string => "172.16.12.0"; # IP address and netmask of your local NTP server + "ntp_mask" + string => "255.255.255.0"; + "ntp_pkgs" + slist => { "ntp" }; # NTP packages to be installed to ensure service + +# Define a class for the NTP server + classes: + any:: + "ntp_hosts" + or => { classmatch(canonify("ipv4_$(ntp_server)")) }; + +# Ensure that the NTP packages are installed + packages: + ubuntu:: + "$(ntp_pkgs)" + comment => "setup NTP", + package_policy => "add", + package_method => generic; + +# Ensure existence of file and directory for NTP drift learning statistics + files: + linux:: + "/var/lib/ntp/ntp.drift" + comment => "Enable ntp service", + create => "true"; + "/var/log/ntpstats/." + comment => "Create a statistic directory", + perms => mog("644","ntp","ntp"), + create => "true"; + ntp_hosts:: + # Build the cache configuration file for the NTP server + "/var/cfengine/cache/ntp.conf" + comment => "Build $(this.promiser) cache file for NTP server", + create => "true", + edit_defaults => empty, + edit_line => restore_ntp_master("$(ntp_network)","$(ntp_mask)"); + centos.ntp_hosts:: + # Copy the cached configuration file to its target destination + "$(ntp_conf)" + comment => "Ensure $(this.promiser) in a perfect condition", + copy_from => local_cp("$(cache_dir)/ntp.conf"), + classes => if_repaired("refresh_ntpd_centos"); + ubuntu.ntp_hosts:: + "$(ntp_conf)" + comment => "Ensure $(this.promiser) in a perfect condition", + copy_from => local_cp("$(cache_dir)/ntp.conf"), + classes => if_repaired("refresh_ntpd_ubuntu"); + !ntp_hosts:: + # Build the cache configuration file for the NTP client + "$(cache_dir)/ntp.conf" + comment => "Build $(this.promiser) cache file for NTP client", + create => "true", + edit_defaults => empty, + edit_line => restore_ntp_client("$(ntp_server)"); + centos.!ntp_hosts:: + # Copy the cached configuration file to its target destination + "$(ntp_conf)" + comment => "Ensure $(this.promiser) in a perfect condition", + copy_from => local_cp("$(cache_dir)/ntp.conf"), + classes => if_repaired("refresh_ntpd_centos"); + ubuntu.!ntp_hosts:: + "$(ntp_conf)" + comment => "Ensure $(this.promiser) in a perfect condition", + copy_from => local_cp("$(cache_dir)/ntp.conf"), + classes => if_repaired("refresh_ntpd_ubuntu"); + +# Set classes (conditions) for to restart the NTP daemon if there have been any changes to configuration + processes: + centos:: + "ntpd.*" + restart_class => "refresh_ntpd_centos"; + ubuntu:: + "ntpd.*" + restart_class => "refresh_ntpd_ubuntu"; + +# Restart the NTP daemon if the configuration has changed + commands: + refresh_ntpd_centos:: + "/etc/init.d/ntpd restart"; + refresh_ntpd_ubuntu:: + "/etc/init.d/ntp restart"; + +} + +####################################################### + +bundle edit_line restore_ntp_master(network,mask) +{ + vars: + "list" + string => "###################################### +# ntp.conf-master + +driftfile /var/lib/ntp/ntp.drift +statsdir /var/log/ntpstats/ + +statistics loopstats peerstats clockstats +filegen loopstats file loopstats type day enable +filegen peerstats file peerstats type day enable +filegen clockstats file clockstats type day enable + +# Use public servers from the pool.ntp.org project. +# Please consider joining the pool (http://www.pool.ntp.org/join.html). +# Consider changing the below servers to a location near you for better time +# e.g. server 0.europe.pool.ntp.org, or server 0.no.pool.ntp.org etc. +server 0.centos.pool.ntp.org +server 1.centos.pool.ntp.org +server 2.centos.pool.ntp.org + +# Permit time synchronization with our time source, but do not +# permit the source to query or modify the service on this system. +restrict -4 default kod nomodify notrap nopeer noquery +restrict -6 default kod nomodify notrap nopeer noquery + +# Permit all access over the loopback interface. This could +# be tightened as well, but to do so would effect some of +# the administrative functions. +restrict 127.0.0.1 +restrict ::1 + +# Hosts on local network are less restricted. +restrict $(network) mask $(mask) nomodify notrap"; + + insert_lines: + "$(list)"; +} + +####################################################### + +bundle edit_line restore_ntp_client(serverip) +{ + vars: + "list" + string => "###################################### +# This file is protected by cfengine # +###################################### +# ntp.conf-client + +driftfile /var/lib/ntp/ntp.drift +statsdir /var/log/ntpstats/ + +statistics loopstats peerstats clockstats +filegen loopstats file loopstats type day enable +filegen peerstats file peerstats type day enable +filegen clockstats file clockstats type day enable + +# Permit time synchronization with our time source, but do not +# permit the source to query or modify the service on this system. +restrict -4 default kod nomodify notrap nopeer noquery +restrict -6 default kod nomodify notrap nopeer noquery + +# Permit all access over the loopback interface. This could +# be tightened as well, but to do so would effect some of +# the administrative functions. +restrict 127.0.0.1 +restrict ::1 +server $(serverip) +restrict $(serverip) nomodify"; + + insert_lines: + "$(list)"; +} ``` This policy can be found in `/var/cfengine/share/doc/examples/example_ntp.cf` @@ -242,23 +196,17 @@ This policy can be found in `/var/cfengine/share/doc/examples/example_ntp.cf` If you don't want to build a server, you might do like this: ```cf3 - bundle agent time_management - { - vars: - - any:: - - "ntp_server" string => "no.pool.ntp.org"; - - commands: - - any:: - - "/usr/sbin/ntpdate $(ntp_server)" - - contain => silent; - - } +bundle agent time_management +{ + vars: + any:: + "ntp_server" + string => "no.pool.ntp.org"; + commands: + any:: + "/usr/sbin/ntpdate $(ntp_server)" + contain => silent; +} ``` This is a hard reset of the time, it corrects it immediately. This may cause problems diff --git a/examples/example-snippets/promise-patterns/example_process_kill.markdown b/examples/example-snippets/promise-patterns/example_process_kill.markdown index 79bacc3ee..b1856d794 100644 --- a/examples/example-snippets/promise-patterns/example_process_kill.markdown +++ b/examples/example-snippets/promise-patterns/example_process_kill.markdown @@ -2,7 +2,6 @@ layout: default title: Ensure a process is not running published: true -tags: [Examples, Policy, process, kill] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -32,31 +31,45 @@ This policy can be found in `/var/cfengine/share/doc/examples/unit_process_kill. Example run: +```command +/bin/sleep 1000 & ``` -# /bin/sleep 1000 & +```output [1] 5370 -# cf-agent -f unit_process_kill.cf +``` + +```command +cf-agent -f unit_process_kill.cf +``` +```output [1]+ Terminated /bin/sleep 1000 -# ``` Now let's do it again with inform mode turned on, and CFEngine will show the process table entry that matched the pattern we specified ("sleep"): +```command +/bin/sleep 1000 & ``` -# /bin/sleep 1000 & +```output [1] 5377 -# cf-agent -f unit_process_kill.cf -IK +``` + +```command +cf-agent -f unit_process_kill.cf -IK +``` +```output 2013-06-08T16:30:06-0700 info: This agent is bootstrapped to '192.168.183.208' 2013-06-08T16:30:06-0700 info: Running full policy integrity checks 2013-06-08T16:30:06-0700 info: /process_kill/processes/'sleep': Signalled 'term' (15) to process 5377 (root 5377 3854 5377 0.0 0.0 11352 0 612 1 16:30 00:00:00 /bin/sleep 1000) [1]+ Terminated /bin/sleep 1000 -# ``` If we add the -v switch to turn on verbose mode, we see the /bin/ps command CFEngine used to dump the process table: +```command +cf-agent -f unit_process_kill.cf -Kv ``` -# cf-agent -f unit_process_kill.cf -Kv +```output ... 2013-06-08T16:38:20-0700 verbose: Observe process table with /bin/ps -eo user,pid,ppid,pgid,pcpu,pmem,vsz,ni,rss,nlwp,stime,time,args 2013-06-08T16:38:20-0700 verbose: Matched 'root 5474 3854 5474 0.0 0.0 11352 0 612 1 16:38 00:00:00 /bin/sleep 1000' diff --git a/examples/example-snippets/promise-patterns/example_process_restart.markdown b/examples/example-snippets/promise-patterns/example_process_restart.markdown index 3de77bf7f..99ab45ab8 100644 --- a/examples/example-snippets/promise-patterns/example_process_restart.markdown +++ b/examples/example-snippets/promise-patterns/example_process_restart.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Restart a Process +title: Restart a process published: true -tags: [Examples, Policy, process, restart] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -65,13 +64,17 @@ root 8008 1 0 18:18 ? 00:00:00 /var/cfengine/bin/cf-serverd And again, in Inform mode: +```command +kill 8008 ``` -# kill 8008 -# cf-agent -f unit_process_restart.cf -I + +```command +cf-agent -f unit_process_restart.cf -I +``` +```output 2013-06-08T18:19:51-0700 info: This agent is bootstrapped to '192.168.183.208' 2013-06-08T18:19:51-0700 info: Running full policy integrity checks 2013-06-08T18:19:51-0700 info: /process_restart/processes/'$(component)': Making a one-time restart promise for 'cf-serverd' 2013-06-08T18:19:51-0700 info: Executing 'no timeout' ... '/var/cfengine/bin/cf-serverd' 2013-06-08T18:19:52-0700 info: Completed execution of '/var/cfengine/bin/cf-serverd' -# ``` diff --git a/examples/example-snippets/promise-patterns/example_ssh_keys.markdown b/examples/example-snippets/promise-patterns/example_ssh_keys.markdown index dad870c4b..b7a5bb229 100644 --- a/examples/example-snippets/promise-patterns/example_ssh_keys.markdown +++ b/examples/example-snippets/promise-patterns/example_ssh_keys.markdown @@ -2,7 +2,6 @@ layout: default title: Distribute ssh keys published: true -tags: [Examples, Policy, ssh, authorized_keys, distribution] reviewed: 2015-12-15 reviewed-by: nickanderson, enrico --- @@ -15,7 +14,8 @@ the [Masterfiles Policy Framework][Masterfiles Policy Framework]. The you do not have a `def.json` in the root of your masterfiles directory simply create it with the following content. -``` +```json +[file=def.json] { "classes": { "services_autorun": [ "any" ] @@ -58,22 +58,24 @@ root@host001:~# useradd kelly Then update the policy and run it: +```command +cf-agent -Kf update.cf; cf-agent -KI ``` -root@host001:~# cf-agent -Kf update.cf; cf-agent -KI - info: Installing cfe_internal_non_existing_package... - info: Created directory '/home/bob/.ssh/.' - info: Owner of '/home/bob/.ssh' was 0, setting to 1002 - info: Object '/home/bob/.ssh' had permission 0755, changed it to 0700 - info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/bob' - info: Owner of '/home/bob/.ssh/authorized_keys' was 0, setting to 1002 - info: Created directory '/home/frank/.ssh/.' - info: Owner of '/home/frank/.ssh' was 0, setting to 1003 - info: Object '/home/frank/.ssh' had permission 0755, changed it to 0700 - info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/frank' - info: Owner of '/home/frank/.ssh/authorized_keys' was 0, setting to 1003 - info: Created directory '/home/kelly/.ssh/.' - info: Owner of '/home/kelly/.ssh' was 0, setting to 1004 - info: Object '/home/kelly/.ssh' had permission 0755, changed it to 0700 - info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/kelly' - info: Owner of '/home/kelly/.ssh/authorized_keys' was 0, setting to 1004 +```output +info: Installing cfe_internal_non_existing_package... +info: Created directory '/home/bob/.ssh/.' +info: Owner of '/home/bob/.ssh' was 0, setting to 1002 +info: Object '/home/bob/.ssh' had permission 0755, changed it to 0700 +info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/bob' +info: Owner of '/home/bob/.ssh/authorized_keys' was 0, setting to 1002 +info: Created directory '/home/frank/.ssh/.' +info: Owner of '/home/frank/.ssh' was 0, setting to 1003 +info: Object '/home/frank/.ssh' had permission 0755, changed it to 0700 +info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/frank' +info: Owner of '/home/frank/.ssh/authorized_keys' was 0, setting to 1003 +info: Created directory '/home/kelly/.ssh/.' +info: Owner of '/home/kelly/.ssh' was 0, setting to 1004 +info: Object '/home/kelly/.ssh' had permission 0755, changed it to 0700 +info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/kelly' +info: Owner of '/home/kelly/.ssh/authorized_keys' was 0, setting to 1004 ``` diff --git a/examples/example-snippets/promise-patterns/example_sudoers.markdown b/examples/example-snippets/promise-patterns/example_sudoers.markdown index 6e06be863..7d300ee6b 100644 --- a/examples/example-snippets/promise-patterns/example_sudoers.markdown +++ b/examples/example-snippets/promise-patterns/example_sudoers.markdown @@ -2,7 +2,6 @@ layout: default title: Set up sudo published: true -tags: [Examples, Policy, sudo, file editing] reviewed: 2013-06-08 reviewed-by: atsaloli --- @@ -42,31 +41,34 @@ We recommend editing the master sudoers file using `visudo` or a similar tool. I Example run: +```command +cf-agent -f temp.cf -KI ``` -# cf-agent -f temp.cf -KI +```output 2013-06-08T19:13:21-0700 info: This agent is bootstrapped to '192.168.183.208' 2013-06-08T19:13:22-0700 info: Running full policy integrity checks 2013-06-08T19:13:23-0700 info: Copying from '192.168.183.208:/var/cfengine/masterfiles/sudoers' 2013-06-08T19:13:23-0700 info: /sudoers/files/'/tmp/sudoers': Object '/tmp/sudoers' had permission 0600, changed it to 0440 -# ``` For reference we include an example of a simple sudoers file: - # /etc/sudoers - # - # This file MUST be edited with the 'visudo' command as root. - # +``` +# /etc/sudoers +# +# This file MUST be edited with the 'visudo' command as root. +# - Defaults env_reset +Defaults env_reset - # User privilege specification - root ALL=(ALL) ALL +# User privilege specification +root ALL=(ALL) ALL - # Allow members of group sudo to execute any command after they have - # provided their password - %sudo ALL=(ALL) ALL +# Allow members of group sudo to execute any command after they have +# provided their password +%sudo ALL=(ALL) ALL - # Members of the admin group may gain root privileges - %admin ALL=(ALL) ALL - john ALL=(ALL) ALL +# Members of the admin group may gain root privileges +%admin ALL=(ALL) ALL +john ALL=(ALL) ALL +``` diff --git a/examples/example-snippets/promise-patterns/example_updating_from_central_hub.markdown b/examples/example-snippets/promise-patterns/example_updating_from_central_hub.markdown index 44485a98a..ff1897048 100644 --- a/examples/example-snippets/promise-patterns/example_updating_from_central_hub.markdown +++ b/examples/example-snippets/promise-patterns/example_updating_from_central_hub.markdown @@ -2,7 +2,6 @@ layout: default title: Updating from a central policy server published: true -tags: [Examples, Policy, updating, policy server] reviewed: 2013-06-09 reviewed-by: atsaloli --- diff --git a/examples/example-snippets/set_up_hpc_clusters.cf b/examples/example-snippets/set_up_hpc_clusters.cf index 6b63b1d89..c4cac8ad0 100644 --- a/examples/example-snippets/set_up_hpc_clusters.cf +++ b/examples/example-snippets/set_up_hpc_clusters.cf @@ -8,7 +8,7 @@ body executor control mailmaxlines => "30"; # Once per hour, on the hour - schedule => { "Min00_05" }; + schedule => { "Min00" }; } ####################################################### diff --git a/examples/example-snippets/software-adminstration.markdown b/examples/example-snippets/software-adminstration.markdown index 6bb54d0eb..0dd9ae3aa 100644 --- a/examples/example-snippets/software-adminstration.markdown +++ b/examples/example-snippets/software-adminstration.markdown @@ -1,19 +1,18 @@ --- layout: default -title: Software Administration Examples +title: Software administration examples published: true sorting: 4 -tags: [Examples,Software Administration] --- -* [Software and patch installation][Software Administration Examples#Software and patch installation] -* [Postfix mail configuration][Software Administration Examples#Postfix mail configuration] -* [Set up a web server][Software Administration Examples#Set up a web server] -* [Add software packages to the system][Software Administration Examples#Add software packages to the system] -* [Application baseline][Software Administration Examples#Application baseline] -* [Service management (windows)][Software Administration Examples#Service management (windows)] -* [Software distribution][Software Administration Examples#Software distribution] -* [Web server modules][Software Administration Examples#Web server modules] +* [Software and patch installation][Software administration examples#Software and patch installation] +* [Postfix mail configuration][Software administration examples#Postfix mail configuration] +* [Set up a web server][Software administration examples#Set up a web server] +* [Add software packages to the system][Software administration examples#Add software packages to the system] +* [Application baseline][Software administration examples#Application baseline] +* [Service management (windows)][Software administration examples#Service management (windows)] +* [Software distribution][Software administration examples#Software distribution] +* [Web server modules][Software administration examples#Web server modules] * Ensure a service is enabled and running * Managing Software * Install packages diff --git a/examples/example-snippets/system-administration.markdown b/examples/example-snippets/system-administration.markdown index 079a68457..eefc813b9 100644 --- a/examples/example-snippets/system-administration.markdown +++ b/examples/example-snippets/system-administration.markdown @@ -1,39 +1,14 @@ --- layout: default -title: System Administration Examples +title: System administration examples published: true sorting: 12 -tags: [Examples,System Administration] --- -* [Centralized Management][System Administration Examples#Centralized Management] - * [All hosts the same][System Administration Examples#All hosts the same] - * [Variation in hosts][System Administration Examples#Variation in hosts] - * [Updating from a central hub][System Administration Examples#Updating from a central hub] -* [Laptop support configuration][System Administration Examples#Laptop support configuration] -* [Process management][System Administration Examples#Process management] -* [Kill process][System Administration Examples#Kill process] -* [Restart process][System Administration Examples#Restart process] -* [Mount a filesystem][System Administration Examples#Mount a filesystem] -* [Manage a system process][System Administration Examples#Manage a system process] - * [Ensure running][System Administration Examples#Ensure running] - * [Ensure not running][System Administration Examples#Ensure not running] - * [Prune processes][System Administration Examples#Prune processes] -* [Set up HPC clusters][System Administration Examples#Set up HPC clusters] -* [Set up name resolution][System Administration Examples#Set up name resolution] -* [Set up sudo][System Administration Examples#Set up sudo] -* [Environments (virtual)][System Administration Examples#Environments (virtual)] -* [Environment variables][System Administration Examples#Environment variables] -* [Tidying garbage files][System Administration Examples#Tidying garbage files] - -## Centralized Management +## Centralized management These examples show a simple setup for starting with a central approach to management of servers. Centralization of management is a simple approach suitable for small environments with few requirements. It is useful for clusters where systems are all alike. - All hosts the same - Variation in hosts - Updating from a central hub - ### All hosts the same This shows the simplest approach in which all hosts are the same. It is too simple for most environments, but it serves as a starting point. Compare it to the next section that includes variation. @@ -81,7 +56,7 @@ This can be made more sophisticated to handle generic lists: [%CFEngine_include_snippet(restart_process_1.cf, .* )%] -Why? Separating this into two parts gives a high level of control and conistency to CFEngine. There are many options for command execution, like the ability to run commands in a sandbox or as `setuid'. These should not be reproduced in processes. +Why? Separating this into two parts gives a high level of control and conistency to CFEngine. There are many options for command execution, like the ability to run commands in a sandbox or as `setuid`. These should not be reproduced in processes. ## Mount a filesystem ## @@ -164,6 +139,6 @@ Setting up sudo is straightforward, and is best managed by copying trusted files ## Tidying garbage files -Emulating the `tidy' feature of CFEngine 2. +Emulating the `tidy` feature of CFEngine 2. [%CFEngine_include_snippet(tidying_garbage_files.cf, .* )%] diff --git a/examples/example-snippets/system-file.markdown b/examples/example-snippets/system-file.markdown index d70e6e95d..63f931e80 100644 --- a/examples/example-snippets/system-file.markdown +++ b/examples/example-snippets/system-file.markdown @@ -1,9 +1,8 @@ --- layout: default -title: System File Examples +title: System file examples published: true sorting: 13 -tags: [Examples,System Administration,System Files] --- ## Editing password or group files ## @@ -53,7 +52,7 @@ We'll assume that you have a version control repository that is located on some ### Macro template -The next simplest approach to file management is to add variables to the template that will be expanded into local values at the end system, e.g. using variables like '$(sys.host)' for the name of the host within the body of the versioned template. +The next simplest approach to file management is to add variables to the template that will be expanded into local values at the end system, e.g. using variables like `$(sys.host)` for the name of the host within the body of the versioned template. [%CFEngine_include_snippet(macro_template.cf, .* )%] diff --git a/examples/example-snippets/system-information.markdown b/examples/example-snippets/system-information.markdown index 65e85fc37..3c21db39e 100644 --- a/examples/example-snippets/system-information.markdown +++ b/examples/example-snippets/system-information.markdown @@ -1,17 +1,16 @@ --- layout: default -title: System Information Examples +title: System information examples published: true sorting: 11 -tags: [Examples,System Information] --- -* [Change detection][System Information Examples#Change detection] -* [Hashing for change detection (tripwire)][System Information Examples#Hashing for change detection (tripwire)] -* [Check filesystem space][System Information Examples#Check filesystem space] -* [Class match example][System Information Examples#Class match example] -* [Global classes][System Information Examples#Global classes] -* [Logging][System Information Examples#Logging] +* [Change detection][System information examples#Change detection] +* [Hashing for change detection (tripwire)][System information examples#Hashing for change detection (tripwire)] +* [Check filesystem space][System information examples#Check filesystem space] +* [Class match example][System information examples#Class match example] +* [Global classes][System information examples#Global classes] +* [Logging][System information examples#Logging] * Check filesystem space ## Change detection diff --git a/examples/example-snippets/system-security.markdown b/examples/example-snippets/system-security.markdown index f2a6c8e0c..bc79e00ba 100644 --- a/examples/example-snippets/system-security.markdown +++ b/examples/example-snippets/system-security.markdown @@ -1,13 +1,12 @@ --- layout: default -title: System Security Examples +title: System security examples published: true sorting: 10 -tags: [Examples,System Security] --- -* [Distribute root passwords][System Security Examples#Distribute root passwords] -* [Distribute ssh keys][System Security Examples#Distribute ssh keys] +* [Distribute root passwords][System security examples#Distribute root passwords] +* [Distribute ssh keys][System security examples#Distribute ssh keys] * Distribute ssh keys ## Distribute root passwords diff --git a/examples/example-snippets/timing-counting-measuring.markdown b/examples/example-snippets/timing-counting-measuring.markdown index 1e5793182..96cd95856 100644 --- a/examples/example-snippets/timing-counting-measuring.markdown +++ b/examples/example-snippets/timing-counting-measuring.markdown @@ -1,12 +1,11 @@ --- layout: default -title: Measuring Examples +title: Measuring examples published: true sorting: 3 -tags: [Examples, Timing, Counting, Measuring] --- -* [Measurements][Measuring Examples#Measurements] +* [Measurements][Measuring examples#Measurements] ## Measurements diff --git a/examples/example-snippets/user-management.markdown b/examples/example-snippets/user-management.markdown index bcb835f66..0e7e5efef 100644 --- a/examples/example-snippets/user-management.markdown +++ b/examples/example-snippets/user-management.markdown @@ -1,9 +1,8 @@ --- layout: default -title: User Management Examples +title: User management examples published: true sorting: 15 -tags: [Examples,User Management] --- ## Local user management @@ -139,7 +138,7 @@ drwxr-xr-x 5 root root 4096 Dec 22 16:37 .. From the above output we can see that the local users `jack` and `jill` are present, and that they both have home directories. -Now lets activate the example policy and insepect the result. +Now lets activate the example policy and inspect the result. ```console root@debian-jessie:/core/examples# cf-agent -KIf ./local_users_absent.cf diff --git a/examples/example-snippets/windows-registry.markdown b/examples/example-snippets/windows-registry.markdown index f2beaf758..4ae666f7b 100644 --- a/examples/example-snippets/windows-registry.markdown +++ b/examples/example-snippets/windows-registry.markdown @@ -1,14 +1,13 @@ --- layout: default -title: Windows Registry Examples +title: Windows registry examples published: true sorting: 14 -tags: [Examples,Windows Registry] --- -* [Windows registry][Windows Registry Examples#Windows registry] -* [unit_registry_cache.cf][Windows Registry Examples#unit_registry_cache.cf] -* [unit_registry.cf][Windows Registry Examples#unit_registry.cf] +* [Windows registry][Windows registry examples#Windows registry] +* [unit_registry_cache.cf][Windows registry examples#unit_registry_cache.cf] +* [unit_registry.cf][Windows registry examples#unit_registry.cf] ## Windows registry diff --git a/examples/tutorials.markdown b/examples/tutorials.markdown index ce60a722d..4f46923fa 100644 --- a/examples/tutorials.markdown +++ b/examples/tutorials.markdown @@ -3,7 +3,6 @@ layout: default title: Tutorials sorting: 5 published: true -tags: [Examples, Tutorials] --- Familiarize yourself with CFEngine by following these step by step diff --git a/examples/tutorials/custom_inventory.markdown b/examples/tutorials/custom_inventory.markdown index 70b2cf8b7..1b94dc7b8 100644 --- a/examples/tutorials/custom_inventory.markdown +++ b/examples/tutorials/custom_inventory.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Custom Inventory +title: Custom inventory sorting: 15 published: true -tags: [Examples, Tutorials, Inventory, Enterprise] --- This tutorial will show you how to add custom inventory attributes that can be @@ -15,15 +14,15 @@ For a more detailed overview on how the inventory system works please reference This tutorial provides instructions for the following: -* [Choose an attribute][Custom Inventory#Choose an Attribute to Inventory] +* [Choose an attribute][Custom inventory#Choose an attribute to inventory] -* [Create and deploy inventory policy][Custom Inventory#Create and Deploy Inventory Policy] +* [Create and deploy inventory policy][Custom inventory#Create and deploy inventory policy] -* [Run Reports][Custom Inventory#Reporting] +* [Run Reports][Custom inventory#Reporting] **Note:** This tutorial uses the [CFEngine Enterprise Vagrant Environment][Using Vagrant] and files located in the vagrant project directory are automatically available to all hosts. -## Choose an Attribute to Inventory +## Choose an attribute to inventory Writing inventory policy is incredibly easy. Simply add the `inventory` and `attribute_name=` tags to any variable or [namespace scoped classes][classes#scope]. @@ -39,7 +38,7 @@ hub, Operations Team host001, Development ``` -## Create and Deploy Inventory Policy +## Create and deploy inventory policy Now that each of your hosts has access to a data source that provides the Owner information we will write an inventory policy to report that information. @@ -48,6 +47,7 @@ Create `/var/cfengine/masterfiles/services/tutorials/inventory/owner.cf` with th following content: ```cf3 +[file=owner.cf] bundle agent tutorials_inventory_owner # @brief Inventory Owner information # @description Inventory owner information from `/vagrant/inventory_owner.csv`. @@ -67,7 +67,7 @@ bundle agent tutorials_inventory_owner reports: inform_mode:: "$(this.bundle): Discovered Owner='$(my_owner)'" - if => isvaribale( "my_owner" ); + if => isvariable( "my_owner" ); } bundle agent __main__ # @brief Run tutorials_inventory_owner if this policy file is the entry @@ -115,7 +115,6 @@ You can use your favorite JSON validate. I like [`jq`][jq-project], plus it's ha ```console [root@hub ~]# wget -q -O /var/cfengine/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 [root@hub ~]# chmod +x /var/cfengine/bin/jq -[root@hub ~]# ``` Once it's installed, we can use it to validate our JSON. @@ -142,8 +141,10 @@ You can also perform a manual policy run and check that the correct owner is dis **Manual Policy Run:** -```console -[root@hub ~]# cf-agent -KIf /var/cfengine/masterfiles/promises.cf -b tutorials_inventory_owner +```command +cf-agent -KIf /var/cfengine/masterfiles/promises.cf -b tutorials_inventory_owner +``` +```output info: Using command line specified bundlesequence R: tutorials_inventory_owner: Discovered Owner='Operations Team ' ``` @@ -158,7 +159,7 @@ properly. Once you have integrated the policy into `def.json` it will run by all agents after they have updated their policy. Once the hub has had a chance to collect reports the `Owner` attribute will be available to select as a Table column for -Inventory Reports. Custom attributes appear under the `User defined` section. +Inventory reports. Custom attributes appear under the `User defined` section. **Note:** It may take up to 15 minutes for your custom inventory attributes to be collected and made available for reporting. @@ -179,8 +180,10 @@ Let's query the API from the hub itself, and use [`jq`][jq-project] to make it e Now that we have jq in place, let's query the Inventory API to see what inventory attributes are available. -```console -[root@hub ~]# curl -s -k --user admin:admin -X GET https://localhost/api/inventory/attributes-dictionary | jq '.[].attribute_name' +```command +curl -s -k --user admin:admin -X GET https://localhost/api/inventory/attributes-dictionary | jq '.[].attribute_name' +``` +```output "Architecture" "BIOS vendor" "BIOS version" @@ -224,8 +227,10 @@ Yes, we can see our attribute `Owner` is reported. Now, let's query the Inventory API to see what Owners are reported. -```console -[root@hub ~]# curl -s -k --user admin:admin -X POST -H 'content-type: application/json' -d '{ "select": [ "Host name", "Owner" ]}' https://localhost/api/inventory | jq '.data[].rows[]' +```command +curl -s -k --user admin:admin -X POST -H 'content-type: application/json' -d '{ "select": [ "Host name", "Owner" ]}' https://localhost/api/inventory | jq '.data[].rows[]' +``` +```output [ "host001.example.com", "Development " diff --git a/examples/tutorials/dashboard-alerts.markdown b/examples/tutorials/dashboard-alerts.markdown index 707fd3e93..6e8cc0d6b 100644 --- a/examples/tutorials/dashboard-alerts.markdown +++ b/examples/tutorials/dashboard-alerts.markdown @@ -1,14 +1,13 @@ --- layout: default -title: Dashboard Alerts +title: Dashboard alerts sorting: 15 published: true -tags: [Examples, Tutorials, Dashboard, Alerts, Enterprise] --- At 5 minutes intervals, the CFEngine hub gathers information from all of its connected agents about the current state of the system, including the outcome of its runs. All of this information is available to you. In this tutorial we will show how to use the Dashboard to create compliance overview at a glance -**Note:** This tutorial builds upon [another tutorial that manages local users][Manage local users]. +**Note:** This tutorial builds upon [another tutorial that manages local users][Managing local users]. We will create 3 alerts, one that shows when CFEngine repairs the system (promise repaired), one that shows when CFEngine does not need to make a change (promise kept), and one that shows CFEngine failing to repair the system (promise not kept). diff --git a/examples/tutorials/distribute-files-from-a-central-location.markdown b/examples/tutorials/distribute-files-from-a-central-location.markdown index 120f3e823..77a5504f3 100644 --- a/examples/tutorials/distribute-files-from-a-central-location.markdown +++ b/examples/tutorials/distribute-files-from-a-central-location.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Distribute files from a central location +title: Distributing files from a central location sorting: 10 published: true -tags: [Examples, Tutorials, file distribution] --- CFEngine can manage many machines simply by distributing policies to all its hosts. @@ -19,11 +18,15 @@ perform the following instructions: CFEngine stores the master copy of all policy in the `/var/cfengine/masterfiles` directory. Ensure that you are working with the latest version of your `masterfiles`. +```command +git clone url +``` - git clone url or - git pull origin master +```command +git pull origin master +``` ## Make policy changes @@ -33,7 +36,7 @@ Before files can be copied we must know where files should be copied from and where files should be copied to. If these locations are used by multiple components, then defining them in a [common bundle][Bundles] can reduce repetition. Variables and classes that are defined in common bundles are -accessible by all [CFEngine components][Overview#CFEngine Component Applications and Daemons]. This is +accessible by all [CFEngine components][Overview#CFEngine component applications and daemons]. This is especially useful in the case of file copies because the same variable definition can be used both by the policy server when granting access and by the agent host when performing the copy. @@ -44,7 +47,8 @@ These variables provide path definitions for storing and deploying patches. Add the following variable information to the `masterfiles/def.cf` file: -``` +```cf3 +[file=def.cf] "dir_patch_store" string => "/storage/patches", comment => "Define patch files source location", @@ -59,7 +63,7 @@ Add the following variable information to the `masterfiles/def.cf` file: ``` These common variables can be referenced from the rest of the policy by using their fully - [qualified names][Variables#Scalar Referencing and Expansion], + [qualified names][Variables#Scalar referencing and expansion], `$(def.dir_patch_store)` and `$(def.dir_patch_deploy)` ### Grant file access @@ -72,6 +76,7 @@ promise type in a `server` bundle. The default access rules defined by the MPF ( There is no need to modify the vendored policy, instead define your own server bundle. For our example, add the following to `services/main.cf`: ```cf3 +[file=main.cf] bundle server my_access_rules { access: @@ -91,6 +96,7 @@ use is a good idea. This information is stored in a custom library. Create a custom library called `lib/custom/files.cf`. Add the following content: ```cf3 +[file=files.cf] bundle agent sync_from_policyserver(source_path, dest_path) # @brief Sync files from the policy server to the agent # @@ -116,6 +122,7 @@ policy by services. Create `services/patching.cf` with the following content: ```cf3 +[file=patching.cf] # Patching Policy bundle agent patching @@ -214,24 +221,39 @@ This tracker allows you to see how the policy reacts as it is activated on your Always inspect what you expect. `git status` shows the status of your current branch. - git status +```command +git status +``` + +Inspect the changes contained in each file. -Inspect the changes contained in each file. Once satisfied, add them to Git's commit staging area. +```command +git diff file +``` + +Once satisfied, add them to Git's commit staging area. - git diff file - git add file +```command +git add file +``` Iterate over using git **diff**, **add**, and **status** until all of the changes that you expected are listed as **Changes to be committed**. Check the status once more before you commit the changes. - git status +```command +git status +``` Commit the changes to your local repository. - git commit +```command +git commit +``` Push the changes to the central repository so they can be pulled down to your policy server for distribution. - git push origin master +```command +git push origin master +``` diff --git a/examples/tutorials/file_comparison.markdown b/examples/tutorials/file_comparison.markdown index f671ff697..277ed5cea 100644 --- a/examples/tutorials/file_comparison.markdown +++ b/examples/tutorials/file_comparison.markdown @@ -1,24 +1,22 @@ --- layout: default -title: File Comparison +title: File comparison published: true sorting: 100 -tags: [examples, tutorials, file] --- -1. Add the [policy contents][File Comparison#Full Policy] (also can be downloaded from file_compare_test.cf) to a new file, such as /var/cfengine/masterfiles/file_test.cf. +1. Add the [policy contents][File comparison#Full policy] (also can be downloaded from file_compare_test.cf) to a new file, such as /var/cfengine/masterfiles/file_test.cf. 2. Run the following commands as root on the command line: + ```console + export AOUT_BIN="a.out" + export GCC_BIN="/usr/bin/gcc" + export RM_BIN="/bin/rm" + export WORK_DIR=$HOME + export CFE_FILE1="test_plain_1.txt" + export CFE_FILE2="test_plain_2.txt" - ```console - export AOUT_BIN="a.out" - export GCC_BIN="/usr/bin/gcc" - export RM_BIN="/bin/rm" - export WORK_DIR=$HOME - export CFE_FILE1="test_plain_1.txt" - export CFE_FILE2="test_plain_2.txt" - - /var/cfengine/bin/cf-agent /var/cfengine/masterfiles/file_test.cf --bundlesequence robot,global_vars,packages,create_aout_source_file,create_aout,test_delete,do_files_exist_1,create_file_1,outer_bundle_1,copy_a_file,do_files_exist_2,list_file_1,stat,outer_bundle_2,list_file_2 - ``` + /var/cfengine/bin/cf-agent /var/cfengine/masterfiles/file_test.cf --bundlesequence robot,global_vars,packages,create_aout_source_file,create_aout,test_delete,do_files_exist_1,create_file_1,outer_bundle_1,copy_a_file,do_files_exist_2,list_file_1,stat,outer_bundle_2,list_file_2 + ``` Here is the order in which bundles are called in the command line above (some other support bundles are contained within file_test.cf but are not included here): @@ -49,24 +47,24 @@ Sets up some global variables that are used frequently by other bundles. ```cf3 bundle common global_vars { - vars: + vars: - "gccexec" string => getenv("GCC_BIN",255); - "rmexec" string => getenv("RM_BIN",255); + "gccexec" string => getenv("GCC_BIN",255); + "rmexec" string => getenv("RM_BIN",255); - "aoutbin" string => getenv("AOUT_BIN",255); - "workdir" string => getenv("WORK_DIR",255); + "aoutbin" string => getenv("AOUT_BIN",255); + "workdir" string => getenv("WORK_DIR",255); - "aoutexec" string => "$(workdir)/$(aoutbin)"; + "aoutexec" string => "$(workdir)/$(aoutbin)"; - "file1name" string => getenv("CFE_FILE1",255); - "file2name" string => getenv("CFE_FILE2",255); + "file1name" string => getenv("CFE_FILE1",255); + "file2name" string => getenv("CFE_FILE2",255); - "file1" string => "$(workdir)/$(file1name)"; - "file2" string => "$(workdir)/$(file2name)"; + "file1" string => "$(workdir)/$(file1name)"; + "file2" string => "$(workdir)/$(file2name)"; - classes: - "gclass" expression => "any"; + classes: + "gclass" expression => "any"; } ``` @@ -76,26 +74,22 @@ bundle common global_vars Ensures that the gcc package is installed, for later use by the create_aout bundle. ```cf3 - bundle agent packages - { - vars: - - "match_package" slist => { - "gcc" - }; - - packages: - "$(match_package)" - package_policy => "add", - package_method => yum; - - reports: - - gclass:: - "Package gcc installed"; - "*********************************"; - - } +bundle agent packages +{ + vars: + "match_package" + slist => { + "gcc" + }; + packages: + "$(match_package)" + package_policy => "add", + package_method => yum; + reports: + gclass:: + "Package gcc installed"; + "*********************************"; +} ``` ## create_aout_source_file ## @@ -105,26 +99,32 @@ Creates the c source file that will generate a binary application in create_aout ```cf3 bundle agent create_aout_source_file { - # This bundle creates the source file that will be compiled in bundle agent create_aout. # See that bunlde's comments for more information. vars: - # An slist is used here instead of a straight forward string because it doesn't seem possible to create - # line endings using \n when using a string to insert text into a file. - - "c" slist => {"#include ","#include ","#include ","#include ","void main()","{char file1[255];strcpy(file1,\"$(global_vars.file1)\");char file2[255];strcpy(file2,\"$(global_vars.file2)\");struct stat time1;int i = lstat(file1, &time1);struct stat time2;int j = lstat(file2, &time2);if (time1.st_mtime < time2.st_mtime){printf(\"Newer\");}else{if(time1.st_mtim.tv_nsec < time2.st_mtim.tv_nsec){printf(\"Newer\");}else{printf(\"Not newer\");}}}"}; - + # An slist is used here instead of a straight forward string because it doesn't seem possible to create + # line endings using \n when using a string to insert text into a file. + + "c" + slist => { + "#include ", + "#include ", + "#include ", + "#include ", + "void main()", + "{char file1[255];strcpy(file1,\"$(global_vars.file1)\");char file2[255];strcpy(file2,\"$(global_vars.file2)\");struct stat time1;int i = lstat(file1, &time1);struct stat time2;int j = lstat(file2, &time2);if (time1.st_mtime < time2.st_mtime){printf(\"Newer\");}else{if(time1.st_mtim.tv_nsec < time2.st_mtim.tv_nsec){printf(\"Newer\");}else{printf(\"Not newer\");}}}" + }; files: - "$(global_vars.workdir)/a.c" - perms => system, - create => "true", - edit_line => Insert("@(c)"); + "$(global_vars.workdir)/a.c" + perms => system, + create => "true", + edit_line => Insert("@(c)"); reports: - "The source file $(global_vars.workdir)/a.c has been created. It will be used to compile the binary a.out, which will provide more accurate file stats to compare two files than the built in CFEngine functionality for comparing file stats, including modification time. This information will be used to determine of the second of the two files being compared is newer or not."; - "*********************************"; + "The source file $(global_vars.workdir)/a.c has been created. It will be used to compile the binary a.out, which will provide more accurate file stats to compare two files than the built in CFEngine functionality for comparing file stats, including modification time. This information will be used to determine of the second of the two files being compared is newer or not."; + "*********************************"; } ``` @@ -139,29 +139,29 @@ The difference between this application and using CFEngine's built in support fo bundle agent create_aout { - classes: + classes: - "doesfileacexist" expression => fileexists("$(global_vars.workdir)/a.c"); - "doesaoutexist" expression => fileexists("$(global_vars.aoutbin)"); + "doesfileacexist" expression => fileexists("$(global_vars.workdir)/a.c"); + "doesaoutexist" expression => fileexists("$(global_vars.aoutbin)"); vars: - # Removes any previous binary - "rmaout" string => execresult("$(global_vars.rmexec) $(global_vars.aoutexec)","noshell"); + # Removes any previous binary + "rmaout" string => execresult("$(global_vars.rmexec) $(global_vars.aoutexec)","noshell"); - doesfileacexist:: - "compilestr" string => "$(global_vars.gccexec) $(global_vars.workdir)/a.c -o $(global_vars.aoutexec)"; - "gccaout" string => execresult("$(compilestr)","noshell"); + doesfileacexist:: + "compilestr" string => "$(global_vars.gccexec) $(global_vars.workdir)/a.c -o $(global_vars.aoutexec)"; + "gccaout" string => execresult("$(compilestr)","noshell"); reports: - doesfileacexist:: - "gcc output: $(gccaout)"; - "Creating aout using $(compilestr)"; - !doesfileacexist:: - "Cannot compile a.out, $(global_vars.workdir)/a.c does not exist."; - doesaoutexist:: - "The binary application aout has been compiled from the source in the create_aout_source_file bundle. It uses the stat library to compare two files, determine if the modified times are different, and whether the second file is newer than the first. The difference between this application and using CFEngine's built in support for getting file stats (e.g. filestat, isnewerthan), which provides file modification time accurate to a second. However, in order to better compare two files might sometimes require parts of a second as well. The stat library provides the extra support for retrieving the additional information required to get better accuracy (down to parts of a second), and is utilized by the binary application a.out that is compiled within the create_aout bundle."; - "*********************************"; + doesfileacexist:: + "gcc output: $(gccaout)"; + "Creating aout using $(compilestr)"; + !doesfileacexist:: + "Cannot compile a.out, $(global_vars.workdir)/a.c does not exist."; + doesaoutexist:: + "The binary application aout has been compiled from the source in the create_aout_source_file bundle. It uses the stat library to compare two files, determine if the modified times are different, and whether the second file is newer than the first. The difference between this application and using CFEngine's built in support for getting file stats (e.g. filestat, isnewerthan), which provides file modification time accurate to a second. However, in order to better compare two files might sometimes require parts of a second as well. The stat library provides the extra support for retrieving the additional information required to get better accuracy (down to parts of a second), and is utilized by the binary application a.out that is compiled within the create_aout bundle."; + "*********************************"; } ``` @@ -173,10 +173,9 @@ Deletes any previous copy of the test files used in the example. ```cf3 bundle agent test_delete { - files: - "$(global_vars.file1)" - delete => tidy; + "$(global_vars.file1)" + delete => tidy; } ``` @@ -186,32 +185,28 @@ Verifies whether the test files exist or not. ```cf3 bundle agent do_files_exist_1 - { - classes: - - "doesfile1exist" expression => fileexists("$(global_vars.file1)"); - "doesfile2exist" expression => fileexists("$(global_vars.file2)"); + "doesfile1exist" + expression => fileexists("$(global_vars.file1)"); + "doesfile2exist" + expression => fileexists("$(global_vars.file2)"); methods: + doesfile1exist:: + "any" usebundle => delete_file("$(global_vars.file1)"); + doesfile2exist:: + "any" usebundle => delete_file("$(global_vars.file2)"); - doesfile1exist:: - - "any" usebundle => delete_file("$(global_vars.file1)"); - doesfile2exist:: - "any" usebundle => delete_file("$(global_vars.file2)"); reports: - - !doesfile1exist:: - "$(global_vars.file1) does not exist."; - doesfile1exist:: - "$(global_vars.file1) did exist. Call to delete it was made."; - - !doesfile2exist:: - "$(global_vars.file2) does not exist."; - doesfile2exist:: - "$(global_vars.file2) did exist. Call to delete it was made."; + !doesfile1exist:: + "$(global_vars.file1) does not exist."; + doesfile1exist:: + "$(global_vars.file1) did exist. Call to delete it was made."; + !doesfile2exist:: + "$(global_vars.file2) does not exist."; + doesfile2exist:: + "$(global_vars.file2) did exist. Call to delete it was made."; } ``` @@ -225,12 +220,12 @@ bundle agent create_file_1 { files: - "$(global_vars.file1)" - perms => system, - create => "true"; + "$(global_vars.file1)" + perms => system, + create => "true"; reports: - "$(global_vars.file1) has been created"; + "$(global_vars.file1) has been created"; } ``` @@ -241,11 +236,10 @@ Adds some text to the first test file. ```cf3 bundle agent outer_bundle_1 { - files: - - "$(global_vars.file1)" - create => "false", - edit_line => inner_bundle_1; + files: + "$(global_vars.file1)" + create => "false", + edit_line => inner_bundle_1; } ``` @@ -257,12 +251,11 @@ Makes a copy of the test file. bundle agent copy_a_file { files: - - "$(global_vars.file2)" - copy_from => local_cp("$(global_vars.file1)"); + "$(global_vars.file2)" + copy_from => local_cp("$(global_vars.file1)"); reports: - "$(global_vars.file1) has been copied to $(global_vars.file2)"; + "$(global_vars.file1) has been copied to $(global_vars.file2)"; } ``` @@ -273,10 +266,9 @@ Verifies that both test files exist. ```cf3 bundle agent do_files_exist_2 { - methods: - - "any" usebundle => does_file_exist($(global_vars.file1)); - "any" usebundle => does_file_exist($(global_vars.file2)); + methods: + "any" usebundle => does_file_exist($(global_vars.file1)); + "any" usebundle => does_file_exist($(global_vars.file2)); } ``` @@ -287,12 +279,11 @@ Reports the contents of each test file. ```cf3 bundle agent list_file_1 { - methods: - "any" usebundle => file_content($(global_vars.file1)); - "any" usebundle => file_content($(global_vars.file2)); + "any" usebundle => file_content($(global_vars.file1)); + "any" usebundle => file_content($(global_vars.file2)); reports: - "*********************************"; + "*********************************"; } ``` @@ -302,22 +293,22 @@ bundle agent list_file_1 ```cf3 bundle agent exec_aout { - classes: - "doesaoutexist" expression => fileexists("$(global_vars.aoutbin)"); + "doesaoutexist" + expression => fileexists("$(global_vars.aoutbin)"); vars: - doesaoutexist:: - "aout" string => execresult("$(global_vars.aoutexec)","noshell"); + doesaoutexist:: + "aout" + string => execresult("$(global_vars.aoutexec)","noshell"); reports: - doesaoutexist:: - "*********************************"; - "$(global_vars.aoutbin) determined that $(global_vars.file2) is $(aout) than $(global_vars.file1)"; - "*********************************"; - !doesaoutexist:: - "Executable $(global_vars.aoutbin) does not exist."; - + doesaoutexist:: + "*********************************"; + "$(global_vars.aoutbin) determined that $(global_vars.file2) is $(aout) than $(global_vars.file1)"; + "*********************************"; + !doesaoutexist:: + "Executable $(global_vars.aoutbin) does not exist."; } ``` @@ -328,43 +319,41 @@ Compares the modified time of each test file using the binary application compil ```cf3 bundle agent stat { - classes: - - "doesfile1exist" expression => fileexists("$(global_vars.file1)"); - "doesfile2exist" expression => fileexists("$(global_vars.file2)"); + "doesfile1exist" + expression => fileexists("$(global_vars.file1)"); + "doesfile2exist" + expression => fileexists("$(global_vars.file2)"); vars: + doesfile1exist:: - doesfile1exist:: + "file1" string => "$(global_vars.file1)"; + "file2" string => "$(global_vars.file2)"; - "file1" string => "$(global_vars.file1)"; - "file2" string => "$(global_vars.file2)"; + "file1_stat" string => execresult("/usr/bin/stat -c \"%y\" $(file1)","noshell"); + "file1_split1" slist => string_split($(file1_stat)," ",3); + "file1_split2" string => nth("file1_split1",1); + "file1_split3" slist => string_split($(file1_split2),"\.",3); + "file1_split4" string => nth("file1_split3",1); - "file1_stat" string => execresult("/usr/bin/stat -c \"%y\" $(file1)","noshell"); - "file1_split1" slist => string_split($(file1_stat)," ",3); - "file1_split2" string => nth("file1_split1",1); - "file1_split3" slist => string_split($(file1_split2),"\.",3); - "file1_split4" string => nth("file1_split3",1); - - "file2_stat" string => execresult("/usr/bin/stat -c \"%y\" $(file2)","noshell"); - "file2_split1" slist => string_split($(file2_stat)," ",3); - "file2_split2" string => nth("file2_split1",1); - "file2_split3" slist => string_split($(file2_split2),"\.",3); - "file2_split4" string => nth("file2_split3",1); + "file2_stat" string => execresult("/usr/bin/stat -c \"%y\" $(file2)","noshell"); + "file2_split1" slist => string_split($(file2_stat)," ",3); + "file2_split2" string => nth("file2_split1",1); + "file2_split3" slist => string_split($(file2_split2),"\.",3); + "file2_split4" string => nth("file2_split3",1); methods: - - "any" usebundle => exec_aout(); + "any" usebundle => exec_aout(); reports: - doesfile1exist:: - "Parts of a second extracted extracted from stat for $(file1): $(file1_split4). Full stat output for $(file1): $(file1_stat)"; - "Parts of a second extracted extracted from stat for $(file2): $(file2_split4). Full stat output for $(file2): $(file2_stat)"; - "Using the binary Linux application stat to compare two files can help determine if the modified times between two files are different. The difference between the stat application using its additional flags and using CFEngine's built in support for getting and comparing file stats (e.g. filestat, isnewerthan) is that normally the accuracy is only to the second of the file's modified time. In order to better compare two files requires parts of a second as well, which the stat command can provide with some additional flags. Unfortunately the information must be extracted from the middle of a string, which is what the stat bundle accomplishes using the string_split and nth functions."; - "*********************************"; - !doesfile1exist:: - "stat: $(global_vars.file1) and probably $(global_vars.file2) do not exist."; + doesfile1exist:: + "Parts of a second extracted extracted from stat for $(file1): $(file1_split4). Full stat output for $(file1): $(file1_stat)"; + "Parts of a second extracted extracted from stat for $(file2): $(file2_split4). Full stat output for $(file2): $(file2_stat)"; + "Using the binary Linux application stat to compare two files can help determine if the modified times between two files are different. The difference between the stat application using its additional flags and using CFEngine's built in support for getting and comparing file stats (e.g. filestat, isnewerthan) is that normally the accuracy is only to the second of the file's modified time. In order to better compare two files requires parts of a second as well, which the stat command can provide with some additional flags. Unfortunately the information must be extracted from the middle of a string, which is what the stat bundle accomplishes using the string_split and nth functions."; + "*********************************"; + !doesfile1exist:: + "stat: $(global_vars.file1) and probably $(global_vars.file2) do not exist."; } ``` @@ -376,11 +365,10 @@ Modifies the text in the second file. ```cf3 bundle agent outer_bundle_2 { - files: - - "$(global_vars.file2)" - create => "false", - edit_line => inner_bundle_2; + files: + "$(global_vars.file2)" + create => "false", + edit_line => inner_bundle_2; } ``` @@ -391,33 +379,27 @@ Uses `filestat` and `isnewerthan` to compare the two test files to see if the se ```cf3 bundle agent list_file_2 { - methods: - - "any" usebundle => file_content($(global_vars.file1)); - "any" usebundle => file_content($(global_vars.file2)); + "any" usebundle => file_content($(global_vars.file1)); + "any" usebundle => file_content($(global_vars.file2)); classes: - - "ok" expression => isgreaterthan(filestat("$(global_vars.file2)","mtime"),filestat("$(global_vars.file1)","mtime")); - "newer" expression => isnewerthan("$(global_vars.file2)","$(global_vars.file1)"); + "ok" expression => isgreaterthan(filestat("$(global_vars.file2)","mtime"),filestat("$(global_vars.file1)","mtime")); + "newer" expression => isnewerthan("$(global_vars.file2)","$(global_vars.file1)"); reports: - "*********************************"; - ok:: - "Using isgreaterthan+filestat determined that $(global_vars.file2) was modified later than $(global_vars.file1)."; - - !ok:: - "Using isgreaterthan+filestat determined that $(global_vars.file2) was not modified later than $(global_vars.file1)."; - newer:: - "Using isnewerthan determined that $(global_vars.file2) was modified later than $(global_vars.file1)."; - !newer:: - "Using isnewerthan determined that $(global_vars.file2) was not modified later than $(global_vars.file1)."; - + "*********************************"; + ok:: + "Using isgreaterthan+filestat determined that $(global_vars.file2) was modified later than $(global_vars.file1)."; + !ok:: + "Using isgreaterthan+filestat determined that $(global_vars.file2) was not modified later than $(global_vars.file1)."; + newer:: + "Using isnewerthan determined that $(global_vars.file2) was modified later than $(global_vars.file1)."; + !newer:: + "Using isnewerthan determined that $(global_vars.file2) was not modified later than $(global_vars.file1)."; } ``` - -## Full Policy ## +## Full policy [%CFEngine_include_snippet(documentation/examples/tutorials/file_compare_test.cf, .* )%] diff --git a/examples/tutorials/files-tutorial.markdown b/examples/tutorials/files-tutorial.markdown index cdf44f874..9742be889 100644 --- a/examples/tutorials/files-tutorial.markdown +++ b/examples/tutorials/files-tutorial.markdown @@ -1,527 +1,454 @@ --- layout: default -title: Create, Modify, and Delete Files +title: File editing sorting: 10 published: true -tags: [Examples, Tutorials] --- ## Prerequisites ## -* Read the tutorial [Tutorial for Running Examples][Examples and Tutorials#Tutorial for Running Examples] -* Ensure you have read and understand the section on [how to make an example stand alone][Examples and Tutorials#Make the Example Stand Alone] +* Read the tutorial [Tutorial for running examples][Examples and tutorials#Tutorial for running examples] +* Ensure you have read and understand the section on [how to make an example stand alone][Examples and tutorials#Make the example stand alone] * Ensure you have read the note at the end of that section regarding modification of the body common control to the following: ```cf3 -body common control { - - inputs => { - "libraries/cfengine_stdlib.cf", - }; +body common control +{ + inputs => { + "libraries/cfengine_stdlib.cf", + }; } ``` Note: This change is not necessary for supporting each of the examples in this tutorial. It will be included only in those examples that require it. -## List Files ## +## List files ## Note: The following workflow assumes the directory /home/user already exists. If it does not either create the directory or adjust the example to a path of your choosing. 1. Create a file /var/cfengine/masterfiles/file_test.cf that includes the following text: - ```cf3 - bundle agent list_file - { - - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - - reports: - "ls: $(ls)"; - - } - ``` + ```cf3 + [file=file_test.cf] + bundle agent list_file + { + vars: + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); + reports: + "ls: $(ls)"; + } + ``` 2. Run the following command to remove any existing test file at the location we wish to use for testing this example: - ```console - rm /home/user/test_plain.txt - ``` + ```command + rm /home/user/test_plain.txt + ``` 3. Test to ensure there is no file /home/user/test_plain.txt, using the following command (the expected result is that there should be no file listed at the location /home/user/test_plain.txt): - ```console - ls /home/user/test_plain.txt - ``` + ```command + ls /home/user/test_plain.txt + ``` 5. Run the following command to instruct CFEngine to see if the file exists (the expected result is that no report will be generated (because the file does not exist): - ```console - /var/cfengine/bin/cf-agent --no-lock --file /var/cfengine/masterfiles/file_test.cf --bundlesequence list_file - ``` + ```command + /var/cfengine/bin/cf-agent --no-lock --file /var/cfengine/masterfiles/file_test.cf --bundlesequence list_file + ``` 6. Create a file for testing the example, using the following command: - ```console - touch /home/user/test_plain.txt - ``` + ```command + touch /home/user/test_plain.txt + ``` 7. Run the following command to instruct CFEngine to search for the file (the expected result is that a report will be generated, because the file exists): - ```console - /var/cfengine/bin/cf-agent --no-lock --file /var/cfengine/masterfiles/file_test.cf --bundlesequence list_file - ``` + ```command + /var/cfengine/bin/cf-agent --no-lock --file /var/cfengine/masterfiles/file_test.cf --bundlesequence list_file + ``` 8. Double check the file exists, using the following command (the expected result is that there will be a file listed at the location /home/user/test_plain.txt): - ```console - ls /home/user/test_plain.txt - ``` + ```command + ls /home/user/test_plain.txt + ``` 9. Run the following command to remove the file: - ```console - rm /home/user/test_plain.txt - ``` + ```command + rm /home/user/test_plain.txt + ``` -## Create a File ## +## Create a file ## ```cf3 +[file=file_create.cf] bundle agent testbundle { - files: - "/home/user/test_plain.txt" + "/home/user/test_plain.txt" perms => system, create => "true"; } bundle agent list_file { - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); reports: - "ls: $(ls)"; - + "ls: $(ls)"; } - bundle agent list_file_2 { - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - - reports: + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); reports: "ls: $(ls)"; - } - - body perms system { - mode => "0640"; + mode => "0640"; } ``` - +```console ls /home/user/test_plain.txt - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,testbundle,list_file_2 - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,list_file_2 - ls /home/user/test_plain.txt - rm /home/user/test_plain.txt +``` - -## Delete a File ## +## Delete a file ## ```cf3 -body common control { - - inputs => { - "libraries/cfengine_stdlib.cf", - }; +[file=file_delete.cf] +body common control +{ + inputs => { + "libraries/cfengine_stdlib.cf", + }; } bundle agent testbundle { - files: - "/home/user/test_plain.txt" + "/home/user/test_plain.txt" perms => system, create => "true"; } bundle agent test_delete { - files: - "/home/user/test_plain.txt" + "/home/user/test_plain.txt" delete => tidy; } - bundle agent list_file { - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); reports: - "ls: $(ls)"; - + "ls: $(ls)"; } - bundle agent list_file_2 { - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); reports: - "ls: $(ls)"; - + "ls: $(ls)"; } - - body perms system { - mode => "0640"; + mode => "0640"; } ``` - +```bash rm /home/user/test_plain.txt - ls /home/user/test_plain.txt - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,testbundle,list_file_2 - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,list_file_2 - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,test_delete,list_file_2 - ls /home/user/test_plain.txt - rm /home/user/test_plain.txt - +``` (last command will throw an error because the file doesn't exist!) -## Modify a File ## -rm /home/user/test_plain.txt +## Modify a File +```bash +rm /home/user/test_plain.txt ls /home/user/test_plain.txt - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,testbundle,list_file_2 - /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,list_file_2 - +``` ```cf3 -body common control { - - inputs => { - "libraries/cfengine_stdlib.cf", - }; +[file=file_modify.cf] +body common control +{ + inputs => { + "libraries/cfengine_stdlib.cf", + }; } bundle agent testbundle { - files: - "/home/user/test_plain.txt" + "/home/user/test_plain.txt" perms => system, create => "true"; } bundle agent test_delete { - files: - "/home/user/test_plain.txt" + "/home/user/test_plain.txt" delete => tidy; } - bundle agent list_file { - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); reports: - "ls: $(ls)"; - + "ls: $(ls)"; } - bundle agent list_file_2 { - vars: - "ls" slist => lsdir("/home/user","test_plain.txt","true"); - + "ls" + slist => lsdir("/home/user", "test_plain.txt", "true"); reports: - "ls: $(ls)"; - + "ls: $(ls)"; } # Finds the file, if exists calls bundle to edit line - bundle agent outer_bundle_1 { - files: - - "/home/user/test_plain.txt" - create => "false", - edit_line => inner_bundle_1; + files: + "/home/user/test_plain.txt" + create => "false", + edit_line => inner_bundle_1; } # Finds the file, if exists calls bundle to edit line - bundle agent outer_bundle_2 { - files: - - "/home/user/test_plain.txt" - create => "false", - edit_line => inner_bundle_2; + files: + "/home/user/test_plain.txt" + create => "false", + edit_line => inner_bundle_2; } # Inserts lines - bundle edit_line inner_bundle_1 { vars: - - "msg" string => "Helloz to World!"; - + "msg" + string => "Helloz to World!"; insert_lines: "$(msg)"; - } # Replaces lines - bundle edit_line inner_bundle_2 { - replace_patterns: - - "Helloz to World!" + replace_patterns: + "Helloz to World!" replace_with => hello_world; - } body replace_with hello_world { - replace_value => "Hello World"; - occurrences => "all"; + replace_value => "Hello World"; + occurrences => "all"; } - body perms system { - mode => "0640"; + mode => "0640"; } ``` - +```bash /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence list_file,test_delete,list_file_2 - ls /home/user/test_plain.txt - rm /home/user/test_plain.txt +``` -## Copy a File and Edit its Text## +## Copy a file and edit its text## ```cf3 -body common control { - - inputs => { - "libraries/cfengine_stdlib.cf", - }; +[file=file_copy.cf] +body common control +{ + inputs => { + "libraries/cfengine_stdlib.cf", + }; } bundle agent testbundle { - files: - "/home/ichien/test_plain.txt" + "/home/ichien/test_plain.txt" perms => system, create => "true"; - reports: "test_plain.txt has been created"; } bundle agent test_delete { - files: - "/home/ichien/test_plain.txt" + "/home/ichien/test_plain.txt" delete => tidy; } bundle agent do_files_exist - { vars: - - "mylist" slist => { "/home/ichien/test_plain.txt", "/home/ichien/test_plain_2.txt" }; - + "mylist" + slist => { + "/home/ichien/test_plain.txt", + "/home/ichien/test_plain_2.txt", + }; classes: - - "exists" expression => filesexist("@(mylist)"); - + "exists" + expression => filesexist("@(mylist)"); reports: - exists:: - "test_plain.txt and test_plain_2.txt files exist"; - !exists:: - "test_plain.txt and test_plain_2.txt files do not exist"; } - - bundle agent do_files_exist_2 - { vars: - - "mylist" slist => { "/home/ichien/test_plain.txt", "/home/ichien/test_plain_2.txt" }; - + "mylist" + slist => { + "/home/ichien/test_plain.txt", + "/home/ichien/test_plain_2.txt" + }; classes: - - "exists" expression => filesexist("@(mylist)"); - + "exists" + expression => filesexist("@(mylist)"); reports: - exists:: - "test_plain.txt and test_plain_2.txt files both exist"; - !exists:: - "test_plain.txt and test_plain_2.txt files do not exist"; } - - bundle agent list_file_1 { - vars: - "ls1" slist => lsdir("/home/ichien","test_plain.txt","true"); - "ls2" slist => lsdir("/home/ichien","test_plain_2.txt","true"); - - "file_content_1" string => readfile( "/home/ichien/test_plain.txt" , "33" ); - "file_content_2" string => readfile( "/home/ichien/test_plain_2.txt" , "33" ); + "ls1" + slist => lsdir("/home/ichien", "test_plain.txt", "true"); + "ls2" + slist => lsdir("/home/ichien", "test_plain_2.txt", "true"); + "file_content_1" + string => readfile("/home/ichien/test_plain.txt", "33"); + "file_content_2" + string => readfile("/home/ichien/test_plain_2.txt", "33"); reports: - #"ls1: $(ls1)"; - #"ls2: $(ls2)"; - - "Contents of /home/ichien/test_plain.txt = $(file_content_1)"; - "Contents of /home/ichien/test_plain_2.txt = $(file_content_2)"; + # "ls1: $(ls1)"; + # "ls2: $(ls2)"; + "Contents of /home/ichien/test_plain.txt = $(file_content_1)"; + "Contents of /home/ichien/test_plain_2.txt = $(file_content_2)"; } - bundle agent list_file_2 { - vars: - "ls1" slist => lsdir("/home/ichien","test_plain.txt","true"); - "ls2" slist => lsdir("/home/ichien","test_plain_2.txt","true"); - "file_content_1" string => readfile( "/home/ichien/test_plain.txt" , "33" ); - "file_content_2" string => readfile( "/home/ichien/test_plain_2.txt" , "33" ); - + "ls1" + slist => lsdir("/home/ichien", "test_plain.txt", "true"); + "ls2" + slist => lsdir("/home/ichien", "test_plain_2.txt", "true"); + "file_content_1" + string => readfile("/home/ichien/test_plain.txt", "33"); + "file_content_2" + string => readfile("/home/ichien/test_plain_2.txt", "33"); reports: - #"ls1: $(ls1)"; - #"ls2: $(ls2)"; - "Contents of /home/ichien/test_plain.txt = $(file_content_1)"; - "Contents of /home/ichien/test_plain_2.txt = $(file_content_2)"; - + # "ls1: $(ls1)"; + # "ls2: $(ls2)"; + "Contents of /home/ichien/test_plain.txt = $(file_content_1)"; + "Contents of /home/ichien/test_plain_2.txt = $(file_content_2)"; } bundle agent outer_bundle_1 { - files: - - "/home/ichien/test_plain.txt" - create => "false", - edit_line => inner_bundle_1; + files: + "/home/ichien/test_plain.txt" + create => "false", + edit_line => inner_bundle_1; } # Copies file bundle agent copy_a_file { files: - - "/home/ichien/test_plain_2.txt" + "/home/ichien/test_plain_2.txt" copy_from => local_cp("/home/ichien/test_plain.txt"); - reports: - "test_plain.txt has been copied to test_plain_2.txt"; + "test_plain.txt has been copied to test_plain_2.txt"; } bundle agent outer_bundle_2 { - files: - - "/home/ichien/test_plain_2.txt" - create => "false", - edit_line => inner_bundle_2; + files: + "/home/ichien/test_plain_2.txt" + create => "false", + edit_line => inner_bundle_2; } - bundle edit_line inner_bundle_1 { vars: - - "msg" string => "Helloz to World!"; - + "msg" + string => "Helloz to World!"; insert_lines: "$(msg)"; - reports: "inserted $(msg) into test_plain.txt"; - } bundle edit_line inner_bundle_2 { - replace_patterns: - - "Helloz to World!" + replace_patterns: + "Helloz to World!" replace_with => hello_world; - - reports: - "Text in test_plain_2.txt has been replaced"; - + reports: + "Text in test_plain_2.txt has been replaced"; } body replace_with hello_world { - replace_value => "Hello World"; - occurrences => "all"; + replace_value => "Hello World"; + occurrences => "all"; } body perms system { - mode => "0640"; + mode => "0640"; } ``` -```console +```command /var/cfengine/bin/cf-agent --no-lock --file ./file_test.cf --bundlesequence test_delete,do_files_exist,testbundle,outer_bundle_1,copy_a_file,do_files_exist_2,list_file_1,outer_bundle_2,list_file_2 ``` diff --git a/examples/tutorials/high-availability.markdown b/examples/tutorials/high-availability.markdown index 4579282be..2232de00f 100644 --- a/examples/tutorials/high-availability.markdown +++ b/examples/tutorials/high-availability.markdown @@ -1,15 +1,14 @@ --- layout: default -title: High Availability +title: High availability published: true -tags: [cfengine enterprise, high availability] --- ## Overview Although CFEngine is a distributed system, with decisions made by autonomous agents running on each node, the hub can be viewed as a single point of failure. In order to be able to play both roles -that hub is responsible for - policy serving and report collection - High Availability feature was +that hub is responsible for - policy serving and report collection - High availability feature was introduced in 3.6.2. Essentially it is based on well known and broadly used cluster resource management tools - [corosync](https://corosync.github.io/corosync/) and [pacemaker](https://clusterlabs.org/pacemaker/) as well as PostgreSQL streaming replication feature. @@ -17,14 +16,14 @@ management tools - [corosync](https://corosync.github.io/corosync/) and ## Design -CFEngine High Availability is based on redundancy of all components, most importantly the PostgreSQL +CFEngine High availability is based on redundancy of all components, most importantly the PostgreSQL database. Active-passive PostgreSQL database configuration is the essential part of High Availability feature. While PostgreSQL supports different replication methods and active-passive configuration schemes, it doesn't provide out-of-the-box database failover-failback mechanism. To support that the well established cluster resources management solution based on the Linux-HA project was selected. -Overview of CFEngine High Availability is shown in the diagram below. +Overview of CFEngine High availability is shown in the diagram below. ![HASetup](ha_3.6.png) @@ -55,7 +54,7 @@ documentation](https://wiki.postgresql.org/wiki/Streaming_Replication). ## CFEngine -In a High Availability setup all the clients are aware of existence of more than one hub. Current +In a High availability setup all the clients are aware of existence of more than one hub. Current active hub is selected as a policy server and policy fetching and report collection is done by the active hub. One of the differences comparing to single-hub installation is that instead of having one policy server, clients have a list of hubs where they should fetch policy and initiate report @@ -67,12 +66,12 @@ already established trust with the passive hub as well. ### Mission Portal -Mission Portal since 3.6.2 has a new indicator whitch shows the status of the High Availability +Mission Portal since 3.6.2 has a new indicator whitch shows the status of the High availability configuration. HAHealth -High Availability status is constantly monitored so that once some malfunction is discovered the +High availability status is constantly monitored so that once some malfunction is discovered the user is notified about the degraded state of the system. Besides simple visualization of High Availability, the user is able to get detailed information regarding the reason for a degraded state, as well as when data was last reported from each hub. This gives quite comprehensive @@ -84,16 +83,16 @@ knowledge and overview of the whole setup. ### Inventory There are also new Mission Portal inventory variables indicating the IP address of the active hub -instance and status of the High Availability installation on each of the hubs. Looking at inventory -reports is especially helpful to diagnose any problems when High Availability is reported as +instance and status of the High availability installation on each of the hubs. Looking at inventory +reports is especially helpful to diagnose any problems when High availability is reported as *degraded*. HAInventory -### CFEngine High Availability installation +### CFEngine high availability installation -Existing CFEngine Enterprise installations can upgrade their single-node hub to a High Availability +Existing CFEngine Enterprise installations can upgrade their single-node hub to a High availability system in versions 3.6.2 and newer. Detailed instructions how to upgrade from single hub to High -Availability or how to install CFEngine High Availability from scratch can be found in the -[Installation Guide][Installation Guide]. +Availability or how to install CFEngine High availability from scratch can be found in the +[Installation guide][Installation guide]. diff --git a/examples/tutorials/high-availability/installation-guide.markdown b/examples/tutorials/high-availability/installation-guide.markdown index a92fc9df6..fa4a82114 100644 --- a/examples/tutorials/high-availability/installation-guide.markdown +++ b/examples/tutorials/high-availability/installation-guide.markdown @@ -1,20 +1,19 @@ --- layout: default published: true -title: Installation Guide -tags: [cfengine enterprise, high availability] +title: Installation guide --- ## Overview ## -This tutorial is describing the installation steps of the **CFEngine High Availability** feature. It +This tutorial is describing the installation steps of the **CFEngine High availability** feature. It is suitable for both upgrading existing CFEngine installations to HA and for installing HA from -scratch. Before starting installation we strongly recommend reading the [CFEngine High Availability -overview][High Availability]. +scratch. Before starting installation we strongly recommend reading the [CFEngine High availability +overview][High availability]. ## Installation procedure ## -As with most High Availability systems, setting it up requires carefully following a series of steps +As with most High availability systems, setting it up requires carefully following a series of steps with dependencies on network components. The setup can therefore be error-prone, so if you are a CFEngine Enterprise customer we recommend that you contact support for assistance if you do not feel 100% comfortable of doing this on your own. @@ -57,7 +56,7 @@ Detailed network configuration is shown on the picture below: **On both nodes:** - ``` + ```command yum -y install pcs pacemaker cman fence-agents ``` @@ -86,20 +85,20 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 4. Authenticate hacluster user for each node of the cluster. Run the command below **on the node1**: - ``` + ```command pcs cluster auth node1 node2 -u hacluster ``` After entering password, you should see a message similar to one below: - ``` + ```output node1: Authorized node2: Authorized ``` 5. Create the cluster by running the following command **on the node1**: - ``` + ```command pcs cluster setup --name cfcluster node1 node2 ``` @@ -108,7 +107,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 6. Give the cluster time to settle (cca 1 minute) and then start the cluster by running the following command **on the node1**: - ``` + ```command pcs cluster start --all ``` @@ -117,7 +116,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 7. At this point the cluster should be up and running. Running ```pcs status``` should print something similar to the output below. - ``` + ```output Cluster name: cfcluster WARNING: no stonith devices and stonith-enabled is not false Stack: cman @@ -160,13 +159,13 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 10. Verify that the cfvirtip resource is properly configured and running. - ``` + ```command pcs status ``` should give something like this: - ``` + ```output Cluster name: cfcluster Last updated: Tue Jul 7 09:29:10 2015 Last change: Fri Jul 3 08:41:24 2015 @@ -189,7 +188,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 1. Install the CFEngine hub package **on both node1 and node2**. 2. Make sure CFEngine is not running (**on both node1 and node2**): - ``` + ```command service cfengine3 stop ``` @@ -233,7 +232,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 4. Do an initial sync of PostgreSQL: 1. Start PostgreSQL **on node1**: - ``` + ```command pushd /tmp; su cfpostgres -c "/var/cfengine/bin/pg_ctl -w -D /var/cfengine/state/pg/data -l /var/log/postgresql.log start"; popd ``` @@ -259,33 +258,33 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 5. Start PostgreSQL on the **node2** by running the following command: - ``` + ```command pushd /tmp; su cfpostgres -c "/var/cfengine/bin/pg_ctl -D /var/cfengine/state/pg/data -l /var/log/postgresql.log start"; popd ``` 6. Check that PostgreSQL replication is setup and working properly: 1. The **node2** should report it is in the recovery mode: - ``` + ```command /var/cfengine/bin/psql -x cfdb -c "SELECT pg_is_in_recovery();" ``` should return: - ``` + ```output -[ RECORD 1 ]-----+-- pg_is_in_recovery | t ``` 2. The **node1** should report it is replicating to node2: - ``` + ```command /var/cfengine/bin/psql -x cfdb -c "SELECT * FROM pg_stat_replication;" ``` should return something like this: - ``` + ```output -[ RECORD 1 ]----+------------------------------ pid | 11401 usesysid | 10 @@ -310,7 +309,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 7. Stop PostgreSQL **on both nodes**: - ``` + ```command pushd /tmp; su cfpostgres -c "/var/cfengine/bin/pg_ctl -D /var/cfengine/state/pg/data -l /var/log/postgresql.log stop"; popd ``` @@ -355,7 +354,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 3. Configure PostgreSQL to work in Master/Slave (active/standby) mode (**on node1**). - ``` + ```command pcs resource master mscfpgsql cfpgsql master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true ``` @@ -371,19 +370,19 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 5. Enable and start the new resource now that it is fully configured (**on node1**). - ``` + ```command pcs resource enable mscfpgsql --wait=30 ``` 6. Verify that the constraints configuration is correct. - ``` + ```command pcs constraint ``` should give: - ``` + ```output Location Constraints: Resource: mscfpgsql Enabled on: node1 (score:INFINITY) (role: Master) @@ -396,13 +395,13 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 7. Verify that the cluster is now fully setup and running. - ``` + ```command crm_mon -Afr1 ``` should give something like: - ``` + ```output Stack: cman Current DC: node1 (version 1.1.18-3.el6-bfe4e80420) - partition with quorum Last updated: Tue Oct 16 14:19:37 2018 @@ -467,7 +466,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri Bootstrap the **node1** to itself and make sure the initial policy (`promises.cf`) evaluation is skipped: - ``` + ```command cf-agent --bootstrap 192.168.100.10 --skip-bootstrap-policy-run ``` @@ -481,7 +480,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 4. Stop CFEngine **on both nodes**. - ``` + ```command service cfengine3 stop ``` @@ -507,7 +506,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri The `@NODE1_PKSHA@` and `@NODE2_PKSHA@` strings are placeholders for the host key hashes of the nodes. Replace the placeholders with real values obtained by (on any node): - ``` + ```command cf-key -s ``` @@ -516,7 +515,8 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 6. **On both nodes,** add the following class definition to the */var/cfengine/masterfiles/def.json* file to enable HA: - ``` + ```json + [file=def.json] { "classes": { "enable_cfengine_enterprise_hub_ha": [ "any::" ] @@ -529,7 +529,7 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 8. Start CFEngine **on both nodes**. - ``` + ```command service cfengine3 start ``` @@ -557,12 +557,13 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri Running the following command **on node1**: - ``` + ```command /var/cfengine/bin/psql cfdb -c "SELECT * FROM pg_stat_replication;" ``` Should give: - ``` + + ```output pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | state | sent_location | write_location | flush_location | replay_location | sync_priority | sync_state ------+----------+------------+------------------+----------------+-----------------+-------------+-------------------------------+-----------+---------------+----------------+----------------+-----------------+---------------+------------ 9252 | 10 | cfpostgres | node2 | 192.168.100.11 | | 58919 | 2015-08-24 07:14:45.925341+00 | streaming | 0/2A7034D0 | 0/2A7034D0 | 0/2A7034D0 | 0/2A7034D0 | 0 | async @@ -574,8 +575,10 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 6. Modify HA JSON configuration file to contain information about the node3 (see CFEngine configuration, step 2). You should have configuration similar to one below: + ```command + cat /var/cfengine/masterfiles/cfe_internal/enterprise/ha/ha_info.json ``` - [root@node3 masterfiles]# cat /var/cfengine/masterfiles/cfe_internal/enterprise/ha/ha_info.json + ```output { "192.168.100.10": { @@ -627,62 +630,71 @@ HA fencing guide](https://access.redhat.com/documentation/en-us/red_hat_enterpri 2. If ```crm_mon -Afr1``` is printing errors similar to the below - ``` - [root@node1]# pcs status - Cluster name: cfcluster - Last updated: Tue Jul 7 11:27:23 2015 - Last change: Tue Jul 7 11:02:40 2015 - Stack: cman - Current DC: node1 - partition with quorum - Version: 1.1.11-97629de - 2 Nodes configured - 3 Resources configured - - Online: [ node1 ] - OFFLINE: [ node2 ] + ```command + pcs status + ``` + ```output + Cluster name: cfcluster + Last updated: Tue Jul 7 11:27:23 2015 + Last change: Tue Jul 7 11:02:40 2015 + Stack: cman + Current DC: node1 - partition with quorum + Version: 1.1.11-97629de + 2 Nodes configured + 3 Resources configured - Full list of resources: + Online: [ node1 ] + OFFLINE: [ node2 ] - Resource Group: cfengine - cfvirtip (ocf::heartbeat:IPaddr2): Started node1 - Master/Slave Set: mscfpgsql [cfpgsql] - Stopped: [ node1 node2 ] + Full list of resources: - Failed actions: - cfpgsql_start_0 on node1 'unknown error' (1): call=13, status=complete, last-rc-change='Tue Jul 7 11:25:32 2015', queued=1ms, exec=137ms - ``` + Resource Group: cfengine + cfvirtip (ocf::heartbeat:IPaddr2): Started node1 + Master/Slave Set: mscfpgsql [cfpgsql] + Stopped: [ node1 node2 ] - you can try to clear the errors by running ```pcs resource cleanup ```. This should clean errors for the appropriate resource and make the cluster restart it. + Failed actions: + cfpgsql_start_0 on node1 'unknown error' (1): call=13, status=complete, last-rc-change='Tue Jul 7 11:25:32 2015', queued=1ms, exec=137ms + ``` - ``` - [root@node1 vagrant]# pcs resource cleanup cfpgsql - Resource: cfpgsql successfully cleaned up + You can try to clear the errors by running ```pcs resource cleanup ```. This should clean errors for the appropriate resource and make the cluster restart it. - [root@node1 vagrant]# pcs status - Cluster name: cfcluster - Last updated: Tue Jul 7 11:29:36 2015 - Last change: Tue Jul 7 11:29:08 2015 - Stack: cman - Current DC: node1 - partition with quorum - Version: 1.1.11-97629de - 2 Nodes configured - 3 Resources configured + ```command + pcs resource cleanup cfpgsql + ``` + ```output + Resource: cfpgsql successfully cleaned up + ``` + ```command + pcs status + ``` + ```output + Cluster name: cfcluster + Last updated: Tue Jul 7 11:29:36 2015 + Last change: Tue Jul 7 11:29:08 2015 + Stack: cman + Current DC: node1 - partition with quorum + Version: 1.1.11-97629de + 2 Nodes configured + 3 Resources configured - Online: [ node1 ] - OFFLINE: [ node2 ] + Online: [ node1 ] + OFFLINE: [ node2 ] - Full list of resources: + Full list of resources: - Resource Group: cfengine - cfvirtip (ocf::heartbeat:IPaddr2): Started node1 - Master/Slave Set: mscfpgsql [cfpgsql] - Masters: [ node1 ] - Stopped: [ node2 ] - ``` + Resource Group: cfengine + cfvirtip (ocf::heartbeat:IPaddr2): Started node1 + Master/Slave Set: mscfpgsql [cfpgsql] + Masters: [ node1 ] + Stopped: [ node2 ] + ``` 3. After cluster crash make sure to always start the node that should be active first, and then the one that should be passive. If the cluster is not running on the given node after restart you can enable it by running the following command: - ``` - [root@node2]# pcs cluster start - Starting Cluster... - ``` + ```command + pcs cluster start + ``` + ```output + Starting Cluster... + ``` diff --git a/examples/tutorials/installing-cfengine-enterprise-agent.markdown b/examples/tutorials/installing-cfengine-enterprise-agent.markdown index 54a1c4c28..5ff0f2b15 100644 --- a/examples/tutorials/installing-cfengine-enterprise-agent.markdown +++ b/examples/tutorials/installing-cfengine-enterprise-agent.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Installing CFEngine Enterprise Agent +title: Installing CFEngine Enterprise agent published: true sorting: 3 -tags: [getting started, tutorial] --- @@ -15,6 +14,7 @@ This is the full version of CFEngine Enterprise host, but the number of hosts is **System requirements** CFEngine Hosts (clients) + * 32/64-bit machines with a recent version of Linux * 20 mb of memory * 20mb of disk space @@ -25,14 +25,14 @@ The installation script below has been tested on Red Hat, CentOS, SUSE, Debian a 1. Download and Install CFEngine Host Run the following command to download and automatically install CFEngine on a 32-bit or 64-bit Linux machine (the script will detect correct flavor and architecture). -```console +```command wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh agent ``` 2. Bootstrap the Host Once installed, the host needs to bootstrap to your CFEngine policy server. -```console +```command sudo /var/cfengine/bin/cf-agent --bootstrap ``` If you encounter any issue, please make sure the host is on the same domain/subnet as CFEngine policy server will only allow connection from these trusted sources as default configuration. @@ -42,10 +42,10 @@ The CFEngine host is installed and ready. That was easy, wasn't it? If you would like to see what version of CFEngine you are running, type: -```console +```command /var/cfengine/bin/cf-promises --version ``` Now, you have a client-server CFEngine running. If you would like to install more hosts, simply repeat steps 1 to 3 above. You are free to have up to 25 hosts. Enjoy! -Once you have installed the number of hosts you want, a good next step would be to take a look at our [How-to write your first policy][Write cfengine policy] tutorial. +Once you have installed the number of hosts you want, a good next step would be to take a look at our [How-to write your first policy][Writing CFEngine policy] tutorial. diff --git a/examples/tutorials/integrating-alerts-with-pager-duty.markdown b/examples/tutorials/integrating-alerts-with-pager-duty.markdown index 3703765e7..3a745e5e9 100644 --- a/examples/tutorials/integrating-alerts-with-pager-duty.markdown +++ b/examples/tutorials/integrating-alerts-with-pager-duty.markdown @@ -3,7 +3,6 @@ layout: default title: Integrating alerts with PagerDuty sorting: 15 published: true -tags: [Examples, Tutorials, Alerts, Enterprise, Custom Actions, PagerDuty] --- In this How To tutorial we will show you can integrate with [PagerDuty](http://www.pagerduty.com/) using the CFEngine notification dashboard. @@ -21,8 +20,8 @@ We will create a policy that ensures file integrity, and have CFEngine notify Pa Run the following command on your policy server to create the file we want to manage. -```console -# touch /tmp/file-integrity +```command +touch /tmp/file-integrity ``` ## Create a new policy to manage the file @@ -30,6 +29,7 @@ Run the following command on your policy server to create the file we want to ma Insert the following policy into `/tmp/file_example.cf` ```cf3 +[file=file_example.cf] bundle agent file_integrity { files: @@ -56,16 +56,16 @@ Normally, to ensure your policy file is put into action, you would need to follo Normally, to ensure your policy file is put into action, you would need to follow these three steps: - ```console - # mv /tmp/file_example.cf /var/cfengine/masterfiles/ + ```command + mv /tmp/file_example.cf /var/cfengine/masterfiles/ ``` 2. Modify `promises.cf` to include your policy Unless you use version control system, or has a non-standard CFEngine setup, modify your `promises.cf` file by adding the new bundlename and policy-file so it will be picked up by CFEngine to be included in all future runs. - ```console - # vi /var/cfengine/masterfiles/promises.cf + ```command + vi /var/cfengine/masterfiles/promises.cf ``` a) Under the body common control, add `file_integrity` to your *bundlesequence* @@ -80,7 +80,7 @@ Normally, to ensure your policy file is put into action, you would need to follo Next we need to a new service in PagerDuty which we will notify whenever a change is detected by CFEngine. -## Create a new Service in PagerDuty +## Create a new service in PagerDuty 1. Go to PagerDuty.com. In your account, under Services tab, click `Add New Service` @@ -92,7 +92,7 @@ Normally, to ensure your policy file is put into action, you would need to follo 3. Click `Add Service` button. Copy the integration email which we will use in CFEngine. -## Create a new Alert in CFEngine Mission Portal +## Create a new alert in CFEngine Mission Portal 1. Go to the the CFEngine Dashboard and click `Add` button to create a new alert. @@ -122,8 +122,8 @@ Now we have a made a policy to monitor the `/tmp/file-integrity` file. Whenever 1. Make a change to the `/tmp/file_integrity` file on your policy server: - ```console - # echo "Hello World!!" > /tmp/file_integrity + ```command + echo "Hello World!!" > /tmp/file_integrity ``` The next time CFEngine runs, it will detect the change and send an notification to PagerDuty. Go to PagerDuty and wait for an alert to be triggered. diff --git a/examples/tutorials/integrating-alerts-with-ticketing-systems.markdown b/examples/tutorials/integrating-alerts-with-ticketing-systems.markdown index b36d095c4..9acd1311d 100644 --- a/examples/tutorials/integrating-alerts-with-ticketing-systems.markdown +++ b/examples/tutorials/integrating-alerts-with-ticketing-systems.markdown @@ -3,7 +3,6 @@ layout: default title: Integrating alerts with ticketing systems sorting: 15 published: true -tags: [Examples, Tutorials, Alerts, Enterprise, Custom Actions] --- Custom actions can be used to integrate with external 3rd party systems. This tutorial shows how to use a custom action script to open a ticket in Jira when a condition is observed. @@ -18,7 +17,7 @@ As we are already using the JIRA ticketing system to get notified about issues w Note however that it is possible to expand on this by adjusting the Custom action script. For example, we could create reminder tickets, or even automatically close tickets when the alert clears. -## Create a Custom action script that creates a new ticket +## Create a custom action script that creates a new ticket 1. Log in to the console of your CFEngine hub, and make sure you have python and the jira python package installed (normally by running `pip install jira`). @@ -30,7 +29,7 @@ Note however that it is possible to expand on this by adjusting the Custom actio 5. Verify the previous step created a ticket in JIRA. If not, recheck the information to typed in, connectivity and any output generated when running the script. -## Upload the Custom action script to the Mission Portal +## Upload the custom action script to the Mission Portal 1. Log in to the Mission Portal of CFEngine, go to Settings (top right) followed by Custom notification scripts. @@ -40,7 +39,7 @@ Note however that it is possible to expand on this by adjusting the Custom actio 3. Click save to allow the script to be used when creating alerts. -## Create a new alert and associate the Custom action script +## Create a new alert and associate the custom action script 1. Log into the Mission Portal of CFEngine, click the Dashboard tab. @@ -70,4 +69,4 @@ In this tutorial, we have shown how easy it is to integrate with a ticketing sys Using this Custom action, you can choose to open JIRA tickets when some or all of your alerts are triggered. But this is just the beginning; using Custom actions, you can integrate with virtually *any* external system for notifying about- or handling triggered alerts. -Read more in the [Custom action documentation][Custom actions for Alerts]. +Read more in the [Custom action documentation][Custom actions for alerts]. diff --git a/examples/tutorials/integrating-with-sumo-logic.markdown b/examples/tutorials/integrating-with-sumo-logic.markdown index 31bd9f1eb..21053968f 100644 --- a/examples/tutorials/integrating-with-sumo-logic.markdown +++ b/examples/tutorials/integrating-with-sumo-logic.markdown @@ -3,7 +3,6 @@ layout: default title: Integrating with Sumo Logic sorting: 15 published: true -tags: [Examples, Tutorials, Alerts, Enterprise, Custom Actions, Sumo Logic] --- In this How To we will show a simple integrate with [Sumo Logic](http://www.sumologic.com). Whenever there is a CFEngine policy update, that event will be exported to Sumo Logic. These events can become valuable traces when using Sumo Logic to analyze and detect unintendent system behavior. @@ -14,13 +13,13 @@ In this How To we will show a simple integrate with [Sumo Logic](http://www.sumo -# How it works +## How it works Whenever there is a policy update or a new policy is detected by CFEngine, a special variable called "`sys.last_policy_update`" will be updated with current timestamp. We will store this timestamp in a file, and then via api upload the file to Sumo Logic. -# Create the CFEngine Policy file +## Create the CFEngine policy file In this section we will explain the most important parts of our policy file. @@ -86,51 +85,65 @@ That's it! You can copy and paste the whole policy file at the bottom of this pa Save the policy file you make as `/tmp/sumologic_policy_update.cf` -# Ensure the policy always runs +## Ensure the policy always runs Normally, to ensure your policy file is put into action, you would need to follow these two steps: 1. Move the policy file to your masterfiles directory: -```console -# mv /tmp/sumo.cf /var/cfengine/masterfiles/ -``` + ```command + mv /tmp/sumo.cf /var/cfengine/masterfiles/ + ``` 2. Modify `promises.cf` to include your policy Unless you use version control system, or has a non-standard CFEngine setup, modify your `promises.cf` file by adding the new bundle name and policy-file so it will be picked up by CFEngine and be part of all it future runs. -```console -# vi /var/cfengine/masterfiles/promises.cf -``` + ```command + vi /var/cfengine/masterfiles/promises.cf + ``` Under the body common control, add `sumo_logic_policy_update` to your bundle sequence. -![integrating-with-sumo-logic_bundle_sequence.png](integrating-with-sumo-logic_bundle_sequence.png) +```cf3 +body common control + +{ + bundlesequence = { + # Common bundle first (Best Practice) + sumo_logic_policy_update, + inventory_control, + ... +``` Under body common control, add /sumologic\_policy\_update.cf/ to your inputs section. -![integrating-with-sumo-logic_inputs1.png](integrating-with-sumo-logic_inputs1.png) +```cf3 +inputs => { + # File definition for global variables and classes + "sumologic_policy_update.cf", + ... +``` That's all. -# Test it! +## Test it! To test it, we need to make a change to any CFEngine policy, and then go to Sumo Logic to see if there is a new timestamp reported. * Make a change to any policy file, for examle `promises.cf`: -```console -# vi /var/cfengine/masterfiles/promises.cf   +```command +vi /var/cfengine/masterfiles/promises.cf ``` Add a comment and close the file. * Check if timestamp has been updated -```console -# cat /tmp/CFEngine_policy_updated   +```command +cat /tmp/CFEngine_policy_updated ``` * Check with Sumo Logic @@ -145,57 +158,60 @@ As we can see above CFEngine detected a change on `Thursday Oct 2 at 01:16:42` a The policy as found in `sumologic_policy_update.cf`. - bundle agent sumo_logic_policy_update - { - vars: - "policy_update_file" - string => "/tmp/CFEngine_policy_updated"; - "sumo_url" - string => "https://collectors.sumologic.com/receiver/v1/http/"; - "sumo_secret" - string => "MY_SECRET_KEY"; - "curl_args" - string => "-X POST -T $(policy_update_file) $(sumo_url)$(sumo_secret)"; - - files: - "$(policy_update_file)" - create => "true", - edit_line => insert("CFEngine_update: $(sys.last_policy_update)"), - edit_defaults => file; - - "$(policy_update_file)" - classes => if_repaired("new_policy_update"), - changes => change_detections; - - commands: - new_policy_update:: - "/usr/bin/curl" - args => "$(curl_args)", - classes => if_repaired("new_policy_update_sent_to_sumo_logic"), - contain => shell_command, - handle => "New sumo logic event created"; - } - - body changes change_detections - { - hash => "md5"; - update_hashes => "true"; - report_changes => "content"; - report_diffs => "true"; - } - - body contain shell_command - { - useshell => "useshell"; - } - - bundle edit_line insert(str) - { - insert_lines: - "$(str)"; - } - - body edit_defaults file - { - empty_file_before_editing => "true"; - } +```cf3 +[file=sumo_logic_policy_update.cf] +bundle agent sumo_logic_policy_update +{ + vars: + "policy_update_file" + string => "/tmp/CFEngine_policy_updated"; + "sumo_url" + string => "https://collectors.sumologic.com/receiver/v1/http/"; + "sumo_secret" + string => "MY_SECRET_KEY"; + "curl_args" + string => "-X POST -T $(policy_update_file) $(sumo_url)$(sumo_secret)"; + + files: + "$(policy_update_file)" + create => "true", + edit_line => insert("CFEngine_update: $(sys.last_policy_update)"), + edit_defaults => file; + + "$(policy_update_file)" + classes => if_repaired("new_policy_update"), + changes => change_detections; + + commands: + new_policy_update:: + "/usr/bin/curl" + args => "$(curl_args)", + classes => if_repaired("new_policy_update_sent_to_sumo_logic"), + contain => shell_command, + handle => "New sumo logic event created"; +} + +body changes change_detections +{ + hash => "md5"; + update_hashes => "true"; + report_changes => "content"; + report_diffs => "true"; +} + +body contain shell_command +{ + useshell => "useshell"; +} + +bundle edit_line insert(str) +{ + insert_lines: + "$(str)"; +} + +body edit_defaults file +{ + empty_file_before_editing => "true"; +} +``` diff --git a/examples/tutorials/integrating-with-sumo-logic_bundle_sequence.png b/examples/tutorials/integrating-with-sumo-logic_bundle_sequence.png deleted file mode 100644 index 6c1510d5c..000000000 Binary files a/examples/tutorials/integrating-with-sumo-logic_bundle_sequence.png and /dev/null differ diff --git a/examples/tutorials/integrating-with-sumo-logic_inputs1.png b/examples/tutorials/integrating-with-sumo-logic_inputs1.png deleted file mode 100644 index 0b350c535..000000000 Binary files a/examples/tutorials/integrating-with-sumo-logic_inputs1.png and /dev/null differ diff --git a/examples/tutorials/integrating-with-sumo-logic_sumo.png b/examples/tutorials/integrating-with-sumo-logic_sumo.png index 9b09d6332..d0df63b20 100644 Binary files a/examples/tutorials/integrating-with-sumo-logic_sumo.png and b/examples/tutorials/integrating-with-sumo-logic_sumo.png differ diff --git a/examples/tutorials/json-yaml-support-in-cfengine.markdown b/examples/tutorials/json-yaml-support-in-cfengine.markdown index 24e95f4f8..5d7faf689 100644 --- a/examples/tutorials/json-yaml-support-in-cfengine.markdown +++ b/examples/tutorials/json-yaml-support-in-cfengine.markdown @@ -1,9 +1,8 @@ --- layout: default -title: JSON and YAML Support in CFEngine +title: JSON and YAML support in CFEngine published: true sorting: 2 -tags: [json, yaml] --- ## Introduction @@ -78,6 +77,7 @@ expressions or class names. Easy, right? ```cf3 +[file=json_example.cf] body common control { bundlesequence => { "run" }; diff --git a/examples/tutorials/line_editing.markdown b/examples/tutorials/line_editing.markdown deleted file mode 100644 index 0e505ad22..000000000 --- a/examples/tutorials/line_editing.markdown +++ /dev/null @@ -1,7 +0,0 @@ ---- -layout: default -title: Line Editing -published: false -sorting: 3 -tags: [tutorial, json] ---- diff --git a/examples/tutorials/manage-local-users.markdown b/examples/tutorials/manage-local-users.markdown index 1b58e5592..ce8d4f1e4 100644 --- a/examples/tutorials/manage-local-users.markdown +++ b/examples/tutorials/manage-local-users.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Manage local users +title: Managing local users published: true sorting: 3 -tags: [getting started, tutorial] --- @@ -16,8 +15,8 @@ as part of creating the user. Create the files `id_rsa` and `id_rsa.pub` in `/tmp`. -```console -# touch /tmp/id_rsa /tmp/id_rsa.pub +```command +touch /tmp/id_rsa /tmp/id_rsa.pub ``` Create user group security and webadmin. @@ -32,6 +31,7 @@ Create user group security and webadmin. Create a file `/tmp/users.cf` with the following content: ```cf3 +[file=users.cf] body common control { inputs => { "$(sys.libdir)/stdlib.cf" }; @@ -66,30 +66,30 @@ bundle agent setup_home_dir(user) Run CFEngine: -```console -# /var/cfengine/bin/cf-agent -fK /tmp/users.cf +```command +/var/cfengine/bin/cf-agent -fK /tmp/users.cf ``` Verify the result: Have users have been created? -```console -# grep -P "adam|eva" /etc/passwd +```command +grep -P "adam|eva" /etc/passwd ``` Congratulations! You should now see the users adam and eva listed. Verify the result: Have users home directory have been created? -```console -# ls /home | grep -P "adam|eva" +```command +ls /home | grep -P "adam|eva" ``` Congratulations! You should now see adam and eva listed. Verify the result: Have users have been added to the correct groups? -```console -# grep -P "adam|eva" /etc/group +```command +grep -P "adam|eva" /etc/group ``` Congratulations! You should now see adam and eva added to the groups security @@ -99,16 +99,16 @@ you must make sure the groups exists. Verify the result: Have ssh-keys have been copied from `/tmp` to user's `~/.ssh` directory? -```console -# ls /home/adam/.ssh /home/eva/.ssh +```command +ls /home/adam/.ssh /home/eva/.ssh ``` Congratulations! You should now see the files `id_rsa` and `id_rsa.pub`. Ps. If you would like play around with the policy, delete the users after each run with the command -```console -# deluser -r username +```command +deluser -r username ``` Mission accomplished! diff --git a/examples/tutorials/manage-ntp.markdown b/examples/tutorials/manage-ntp.markdown index a37277a63..d691d7749 100644 --- a/examples/tutorials/manage-ntp.markdown +++ b/examples/tutorials/manage-ntp.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Manage Network Time Protocol +title: Managing network time protocol published: true sorting: 3 -tags: [getting started, tutorial] --- In this tutorial we will write a simple policy to ensure that the latest version of the NTP service is installed on your system. Once the NTP software is installed, we will extend the policy to manage the service state as well as the software configuration. @@ -14,6 +13,7 @@ Note: For simplicity, in this tutorial we will work directly on top of the Maste ```cf3 +[file=ntp.cf] bundle agent ntp { vars: @@ -100,6 +100,7 @@ classes => results("bundle", "ntp_package_"); On your hub create `services/ntp.cf` inside *masterfiles* with the following content: ```cf3 +[file=ntp.cf] bundle agent ntp { vars: @@ -135,8 +136,10 @@ Now, we need to make sure the agent knows it should use this policy file and bun Validate it. -```console -[root@hub masterfiles]# python -m json.tool < def.json +```command +python -m json.tool < def.json +``` +```output { "inputs": [ "services/ntp.cf" @@ -151,23 +154,22 @@ Validate it. Force a policy update. Remember, CFEngine is running in the background, so it's possible that by the time you force a policy update and run the agent may have already done it and your output may differ. -``` +```command cf-agent -KIf update.cf ``` In the output, you should see something like: -``` +```output info: Updated '/var/cfengine/inputs/services/ntp.cf' from source '/var/cfengine/masterfiles/services/ntp.cf' on 'localhost' ``` Now force a policy run. -```console -[root@hub masterfiles]# cf-agent -KI -``` - +```command +cf-agent -KI ``` +```output info: Successfully installed package 'ntp' ``` @@ -180,6 +182,7 @@ Now we will extend the policy to ensure that the NTP service is running. Now that the NTP service has been installed on the system, we need to make sure that it is running. ```cf3 +[file=ntp.cf] bundle agent ntp { vars: @@ -268,11 +271,11 @@ If the code has no syntax error, you should see no output. Perform a manual policy run and review the output to ensure that the policy executed successfully. Upon a successful run you should expect to see an output similar to this (depending on the init system your OS is using): -```console -[root@hub masterfiles]# cf-agent -KIf update.cf; +```command +cf-agent -KIf update.cf ; cf-agent -KI +``` +```output info: Copied file '/var/cfengine/masterfiles/services/ntp.cf' to '/var/cfengine/inputs/services/ntp.cf.cfnew' (mode '600') - -[root@hub masterfiles]# cf-agent -KI info: Executing 'no timeout' ... '/sbin/chkconfig ntpd on' info: Command related to promiser '/sbin/chkconfig ntpd on' returned code defined as promise kept 0 info: Completed execution of '/sbin/chkconfig ntpd on' @@ -289,6 +292,7 @@ Now we will manage the configuration file using the built-in mustache templating By default, the NTP service leverages configuration properties specified in /etc/ntp.conf. In this tutorial, we introduce the concept of the files promise type. With this promise type, you can create, delete, and edit files using CFEngine policies. The example policy below illustrates the use of the files promise. +{%raw%} ```cf3 bundle agent ntp { @@ -356,6 +360,7 @@ keys /etc/ntp/keys } ``` +{%endraw%} What does this policy do? @@ -363,7 +368,7 @@ Let's review the different sections of the code, starting with the variable decl #### vars - +{%raw%} ```cf3 vars: linux:: @@ -387,6 +392,7 @@ includefile /etc/ntp/crypto/pw keys /etc/ntp/keys "; ``` +{%endraw%} A few new variables are defined. The variables `ntp_package_name`, `config_file`, `driftfile`, `servers`, and `config_template_string` are defined under the `linux` context (so only linux hosts will define them). `config_file` is the path to the ntp configuration file, `driftfile` and `servers` are both variables that will be used when rendering the configuration file and `config_template_string` is the template that will be used to render the configuration file. While both `driftfile` and `servers` are set the same for all linux hosts, those variables could easily be set to different values under different contexts. @@ -430,7 +436,7 @@ This attribute sets the permissions and ownership of the file. [`mog()`][stdlib- handle => "ntp_files_conf", ``` -A handle uniquely identifies a promise within a policy set. The [policy style guide][Policy Style Guide#promise handles] recommends a naming scheme for the handles e.g. `bundle_name_promise_type_class_restriction_promiser`. Handles are optional, but can be very useful when reviewing logs and can also be used to influence promise ordering with `depends_on`. +A handle uniquely identifies a promise within a policy set. The [policy style guide][Policy style guide#promise handles] recommends a naming scheme for the handles e.g. `bundle_name_promise_type_class_restriction_promiser`. Handles are optional, but can be very useful when reviewing logs and can also be used to influence promise ordering with `depends_on`. ##### classes @@ -477,11 +483,17 @@ Now that we have dissected the policy, let's go ahead and give it a whirl. ### Modify and run the policy -```console -[root@hub masterfiles]# cf-agent -KIf update.cf; - info: Copied file '/var/cfengine/masterfiles/services/ntp.cf' to '/var/cfengine/inputs/services/ntp.cf.cfnew' (mode '600') +```command +cf-agent -KIf update.cf; +``` +```output +info: Copied file '/var/cfengine/masterfiles/services/ntp.cf' to '/var/cfengine/inputs/services/ntp.cf.cfnew' (mode '600') +``` -[root@hub masterfiles]# cf-agent -KI +```command +cf-agent -KI +``` +```output info: Updated rendering of '/etc/ntp.conf' from mustache template 'inline' info: files promise '/etc/ntp.conf' repaired info: Executing 'no timeout' ... '/etc/init.d/ntpd restart' @@ -491,21 +503,25 @@ R: NTP service restarted after configuration change More interestingly, if you examine the configuration file `/etc/ntp.conf`, you will notice that it has been updated with the time `server`(s) and `driftfile` you had specified in the policy, for that specific operating system environment. This is the configuration that the NTP service has been restarted with. -```console -[root@hub masterfiles]# grep -P "^(driftfile|server)" /etc/ntp.conf +```command +grep -P "^(driftfile|server)" /etc/ntp.conf +``` +```output driftfile /var/lib/ntp/drift server time.nist.gov iburst ``` Mission Accomplished! -## Instrumenting for tunability via Augments +## Instrumenting for tunability via augments Next we will augment file/template management with data sourced from a JSON data file. This is a simple extension of what we have done previously illustrating how tunables in policy can be exposed and leveraged from a data feed. CFEngine offers out-of-the-box support for reading and writing JSON data structures. In this tutorial, we will default the NTP configuration properties in policy, but provide a path for the properties to be overridden from Augments. +{% raw %} ```cf3 +[file=ntp.cf] bundle agent ntp { vars: @@ -588,6 +604,7 @@ keys /etc/ntp/keys } ``` +{% endraw %} What does this policy do? @@ -629,12 +646,16 @@ Notice two promises were introduced, one setting `driftfile` to the value of `$( First modify `services/ntp.cf` as shown previously (don't forget to check syntax with `cf-promises` after modification), then run the policy. -```console -[root@hub masterfiles]# cf-agent -KIf update.cf - info: Copied file '/var/cfengine/masterfiles/services/ntp.cf' to '/var/cfengine/inputs/services/ntp.cf.cfnew' (mode '600') - info: Copied file '/var/cfengine/masterfiles/def.json' to '/var/cfengine/inputs/def.json.cfnew' (mode '600') +```command +cf-agent -KIf update.cf +``` +```output +info: Copied file '/var/cfengine/masterfiles/services/ntp.cf' to '/var/cfengine/inputs/services/ntp.cf.cfnew' (mode '600') +info: Copied file '/var/cfengine/masterfiles/def.json' to '/var/cfengine/inputs/def.json.cfnew' (mode '600') +``` -[root@hub masterfiles]# cf-agent -KI +```command +cf-agent -KI ``` We do not expect to see the ntp configuration file modified or the service to be restarted since we have only instrumented the policy so far. @@ -643,6 +664,7 @@ Now, let's modify `def.json` (in the root of masterfiles) and define some differ Modify `def.json` so that it looks like this: ```json +[file=def.json] { "inputs": [ "services/ntp.cf" ], "vars": { @@ -661,8 +683,10 @@ Modify `def.json` so that it looks like this: Now, let's validate the JSON and force a policy run and inspect the result. -```console -[root@hub masterfiles]# python -m json.tool < def.json +```command +python -m json.tool < def.json +``` +```output { "inputs": [ "services/ntp.cf" @@ -684,8 +708,12 @@ Now, let's validate the JSON and force a policy run and inspect the result. } } } +``` -[root@hub masterfiles]# cf-agent -KI +```command +cf-agent -KI +``` +```output info: Updated rendering of '/etc/ntp.conf' from mustache template 'inline' info: files promise '/etc/ntp.conf' repaired info: Executing 'no timeout' ... '/etc/init.d/ntpd restart' @@ -693,8 +721,12 @@ Now, let's validate the JSON and force a policy run and inspect the result. R: NTP service restarted after configuration change info: Can not acquire lock for 'ntp' package promise. Skipping promise evaluation info: Can not acquire lock for 'ntp' package promise. Skipping promise evaluation +``` -[root@hub masterfiles]# grep -P "^(driftfile|server)" /etc/ntp.conf +```command +grep -P "^(driftfile|server)" /etc/ntp.conf +``` +```output driftfile /tmp/drift server 0.north-america.pool.ntp.org iburst server 1.north-america.pool.ntp.org iburst diff --git a/examples/tutorials/manage-packages.markdown b/examples/tutorials/manage-packages.markdown index 7921cf1b7..ce9c09269 100644 --- a/examples/tutorials/manage-packages.markdown +++ b/examples/tutorials/manage-packages.markdown @@ -1,13 +1,10 @@ --- layout: default -title: Manage packages +title: Package management published: true sorting: 3 -tags: [getting started, tutorial] --- - - Package management is a critical task for any system administrator. In this tutorial we will show you how easy it is to install, manage and remove packages using CFEngine. @@ -18,9 +15,10 @@ to make sure the latest version of OpenSSL is installed in all our hosts, we can use the packages promise type, like this: ```cf3 +[file=manage_packages.cf] body common control { - inputs => { "$(sys.libdir)/stdlib.cf"" }; + inputs => { "$(sys.libdir)/stdlib.cf" }; } bundle agent manage_packages @@ -43,12 +41,22 @@ want to use. Defaults can be set up by using the `package_module` common control attribute. When we run this on an CentOS 6 system, we can verify the openssl version before and after running the policy, and we get the following output: -```console -# yum list installed | grep openssl +```command +yum list installed | grep openssl +``` +```output openssl.x86_64 1.0.0-27.el6 @anaconda-CentOS-201303020151.x86_64/6.4 openssl-devel.x86_64 1.0.0-27.el6 @anaconda-CentOS-201303020151.x86_64/6.4 -# cf-agent -K ./manage_packages.cf" -# yum list installed | grep openssl +``` + +```command +cf-agent -K ./manage_packages.cf +``` + +```command +yum list installed | grep openssl +``` +```output openssl.x86_64 1.0.1e-42.el6 @base openssl-devel.x86_64 1.0.1e-42.el6 @base ``` @@ -57,10 +65,17 @@ Additionally, you may want to make sure certain packages are not installed on the system. On my CentOS 6 system, I can see that the telnet package is installed. -```console -# yum list installed | grep telnet +```command +yum list installed | grep telnet +``` +```output telnet.x86_64 1:0.17-48.el6 @base -# which telnet +``` + +```command +which telnet +``` +```output /usr/bin/telnet ``` @@ -68,9 +83,10 @@ Making sure this package is removed from the system is easy. Let's add one more promise to our previous policy, this time using the absent policy: ```cf3 +[file=manage_packages.cf] body common control { - inputs => { "$(sys.libdir)/stdlib.cf"" }; + inputs => { "$(sys.libdir)/stdlib.cf" }; } bundle agent manage_packages @@ -98,9 +114,11 @@ to ensure that the openssl package is always updated to its latest version. We can now see the policy in action: ```console -# cf-agent -K ./manage_packages.cf" +# cf-agent -K ./manage_packages.cf # yum list installed | grep telnet # which telnet +``` +```output /usr/bin/which: no telnet in (/sbin:/bin:/usr/sbin:/usr/bin:/var/cfengine/bin) ``` @@ -121,6 +139,7 @@ Copy `manage_packages.cf` to `/var/cfengine/masterfiles/` on your policy hub. In declaration, and `manage_packages` to the bundlesequence declaration. ```json +[file=def.json] { "inputs": [ "manage_packages.cf" ], "vars": { @@ -131,8 +150,8 @@ declaration, and `manage_packages` to the bundlesequence declaration. Run `cf-promises` on the policy to verify that there are no errors. -``` -# cf-promises -cf /var/cfengine/masterfiles/promises.cf +```command +cf-promises -cf /var/cfengine/masterfiles/promises.cf ``` Wait a few minutes for the new policy to propagate and start taking effect in diff --git a/examples/tutorials/manage-processes-and-services.markdown b/examples/tutorials/manage-processes-and-services.markdown index 53a9910bf..010d8a956 100644 --- a/examples/tutorials/manage-processes-and-services.markdown +++ b/examples/tutorials/manage-processes-and-services.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Manage processes and services +title: Managing processes and services published: true sorting: 3 -tags: [getting started, tutorial] --- @@ -19,6 +18,7 @@ Using CFEngine to ensure certain processes are running is extremely easy. Create a new file called `ensure_process.cf`: ```cf3 +[file=ensure_process.cf] body file control { inputs => { "$(sys.libdir)/stdlib.cf" }; @@ -59,22 +59,26 @@ to true. First, we verify that the ntpd process is not running: -```console -# ps axuww | grep ntp +```command +ps axuww | grep ntp ``` Then we run our CFEngine policy: -```console -# cf-agent -f ./ensure_process.cf +```command +cf-agent -f ./ensure_process.cf +``` +```output 2014-03-20T06:33:56+0000 notice: /default/main/commands/'/etc/init.d/ntp start'[0]: Q: "...init.d/ntp star": * Starting NTP server ntpd Q: "...init.d/ntp star": ...done. ``` Finally, we verify that ntpd is now running on the system: -```console -# ps axuww | grep ntp +```command +ps axuww | grep ntp +``` +```output ntp 5756 0.3 0.1 37696 2172 ? Ss 06:33 0:00 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 104:110 ``` diff --git a/examples/tutorials/masterfiles_policy_framework_upgrade.markdown b/examples/tutorials/masterfiles_policy_framework_upgrade.markdown index 9e999b55f..4abce6561 100644 --- a/examples/tutorials/masterfiles_policy_framework_upgrade.markdown +++ b/examples/tutorials/masterfiles_policy_framework_upgrade.markdown @@ -1,167 +1,143 @@ --- layout: default -title: Masterfiles Policy Framework Upgrade +title: Masterfiles Policy Framework upgrade published: true sorting: 14 -tags: [MPF, upgrade, masterfiles, tutorial] --- -# Introduction +Upgrading the Masterfiles Policy Framework (MPF) is the first step in upgrading CFEngine from one version to another. The MPF should always be the same version or newer than the binary versions running. + +Upgrading the MPF is not an exact process as the details highly depend on the specifics of the changes made to the default policy. This example leverages `git` and shows an example of upgrading a simple policy set based on `3.18.0` to `3.21.2` and can be used as a reference for upgrading your own policy sets. + -Upgrading the Masterfiles Policy Framework (MPF) is an *optional* but **highly -recommended** first step when upgrading CFEngine. -Upgrading the MPF is not an exact process as the details highly depend on the -specifics of the changes made to the default policy. This tutorial leverages -`git` and shows an example of upgrading a simple policy set based on 3.6.7 to -3.7.4 and can be used as a reference for upgrading your own policy sets. # Prepare a Git clone of your working masterfiles -If you are not using Git and instead editing directly in -`$(sys.workdir/masterfiles)` you can simply copy your masterfiles into a new -directory and initalize a new Git repository. - -If you're using Git already simply clone your repository and skip to the next -step. - -```console -[root@hub MPF_upgrade]# rsync -a /var/cfengine/masterfiles/ MPF_upgrade/ -``` - -Then initialize the new Git repository and add all the files to it. - -```console -[root@hub ~]# cd MPF_upgrade/ -[root@hub MPF_upgrade]# git init -Initialized empty Git repository in /root/MPF_upgrade/.git/ -[root@hub MPF_upgrade]# git add -A -[root@hub MPF_upgrade]# git commit -m "Before Upgrade" -[master (root-commit) 108c210] Before Upgrade - 78 files changed, 19980 insertions(+) - create mode 100644 CUSTOM/policy1.cf - create mode 100644 cf_promises_release_id - create mode 100644 cf_promises_validated - create mode 100644 cfe_internal/CFE_cfengine.cf - create mode 100644 cfe_internal/CFE_hub_specific.cf - create mode 100644 cfe_internal/CFE_knowledge.cf - create mode 100644 cfe_internal/cfengine_processes.cf - create mode 100644 cfe_internal/ha/ha.cf - create mode 100644 cfe_internal/ha/ha_def.cf - create mode 100644 cfe_internal/host_info_report.cf - create mode 100644 controls/3.4/cf_serverd.cf - create mode 100644 controls/cf_agent.cf - create mode 100644 controls/cf_execd.cf - create mode 100644 controls/cf_hub.cf - create mode 100644 controls/cf_monitord.cf - create mode 100644 controls/cf_runagent.cf - create mode 100644 controls/cf_serverd.cf - create mode 100644 def.cf - create mode 100644 inventory/any.cf - create mode 100644 inventory/debian.cf - create mode 100644 inventory/generic.cf - create mode 100644 inventory/linux.cf - create mode 100644 inventory/lsb.cf - create mode 100644 inventory/macos.cf - create mode 100644 inventory/os.cf - create mode 100644 inventory/redhat.cf - create mode 100644 inventory/suse.cf - create mode 100644 inventory/windows.cf - create mode 100644 lib/3.5/bundles.cf - create mode 100644 lib/3.5/cfe_internal.cf - create mode 100644 lib/3.5/commands.cf - create mode 100644 lib/3.5/common.cf - create mode 100644 lib/3.5/databases.cf - create mode 100644 lib/3.5/feature.cf - create mode 100644 lib/3.5/files.cf - create mode 100644 lib/3.5/guest_environments.cf - create mode 100644 lib/3.5/monitor.cf - create mode 100644 lib/3.5/packages.cf - create mode 100644 lib/3.5/paths.cf - create mode 100644 lib/3.5/processes.cf - create mode 100644 lib/3.5/reports.cf - create mode 100644 lib/3.5/services.cf - create mode 100644 lib/3.5/storage.cf - create mode 100644 lib/3.6/bundles.cf - create mode 100644 lib/3.6/cfe_internal.cf - create mode 100644 lib/3.6/cfengine_enterprise_hub_ha.cf - create mode 100644 lib/3.6/commands.cf - create mode 100644 lib/3.6/common.cf - create mode 100644 lib/3.6/databases.cf - create mode 100644 lib/3.6/edit_xml.cf - create mode 100644 lib/3.6/examples.cf - create mode 100644 lib/3.6/feature.cf - create mode 100644 lib/3.6/files.cf - create mode 100644 lib/3.6/guest_environments.cf - create mode 100644 lib/3.6/monitor.cf - create mode 100644 lib/3.6/packages.cf - create mode 100644 lib/3.6/paths.cf - create mode 100644 lib/3.6/processes.cf - create mode 100644 lib/3.6/reports.cf - create mode 100644 lib/3.6/services.cf - create mode 100644 lib/3.6/stdlib.cf - create mode 100644 lib/3.6/storage.cf - create mode 100644 lib/3.6/users.cf - create mode 100644 lib/3.6/vcs.cf - create mode 100644 promises.cf - create mode 100644 services/autorun.cf - create mode 100644 services/autorun/custom_policy2.cf - create mode 100644 services/autorun/hello.cf - create mode 100644 services/file_change.cf - create mode 100644 sketches/meta/api-runfile.cf - create mode 100644 templates/host_info_report.mustache - create mode 100644 update.cf - create mode 100644 update/cfe_internal_dc_workflow.cf - create mode 100644 update/cfe_internal_local_git_remote.cf - create mode 100644 update/cfe_internal_update_from_repository.cf - create mode 100644 update/update_bins.cf - create mode 100644 update/update_policy.cf - create mode 100644 update/update_processes.cf -[root@hub MPF_upgrade]# git status -# On branch master -nothing to commit, working directory clean -``` - -Now we have a Git repository that we can start merging in the changes from -upstream. - -# Merge the upstream changes to the MPF into your policy - -## Remove everything except the .git directory. - -By first removing everything we will easily be able so see which files are -*new*, *changed*, *moved* or *removed* upstream. - -```console -[root@hub MPF_upgrade]# rm -rf * - - -[root@hub MPF_upgrade]# git status +We will perform the integration work in `/tmp/MPF-upgrade/integration`. `masterfiles` should exist in the integration directory and is expected to be both the root of your policy set and a `git` repository. + + + + +## Validating expectations + +From `/tmp/MPF-upgrade/integration/masterfiles`. Let's inspect what we expect. + +Is it the root of a policy set? `promises.cf` will be present if so. + +```bash +export INTEGRATION_ROOT="/tmp/MPF-upgrade/integration" + cd $INTEGRATION_ROOT/masterfiles +if [ -e "promises.cf" ]; then + echo "promise.cf exists, it's likely the root of a policy set" +else + echo "promises.cf is missing, $INTEGRATION_ROOT/masterfiles does not seem like the root of a policy set" +fi +``` +```output +promise.cf exists, it's likely the root of a policy set +``` + +Let's see what version of the MPF we are starting from by looking at `version` in `body common control` of `promises.cf`. + +```command +grep -P "\s+version\s+=>" $INTEGRATION_ROOT/masterfiles/promises.cf 2>&1 \ + || echo "promises.cf is missing, $INTEGRATION_ROOT/masterfiles does not seem to be the root of a policy set" +``` +```output +version => "CFEngine Promises.cf 3.18.0"; +``` + +And finally, is it a git repository, what is the last commit? + +```command +git status \ + || echo "$INTEGRATION_ROOT/masterfiles does not appear to be a git repository!" \ + && git log -1 +``` +```output +On branch master +nothing to commit, working tree clean +commit f4c0e120b0b45bcb9ede01ed8fb465f40b4b1e6f +Author: Nick Anderson +Date: Wed Jul 26 18:43:06 2023 -0500 + + CFEngine Policy set prior to upgrade +``` + + + + +# Merge upstream changes from the MPF into your policy + + + + +## Remove everything except the `.git` directory + +By first removing everything we will easily be able so see which files are **new**, **changed**, **moved** or **removed** upstream. + +```command +rm -rf * +``` + +Check `git status` to see that all the files have been deleted and are not staged for commit. + +```command +git status +``` +```output On branch master Changes not staged for commit: (use "git add/rm ..." to update what will be committed) - (use "git checkout -- ..." to discard changes in working directory) - - deleted: CUSTOM/policy1.cf - deleted: cf_promises_release_id - deleted: cf_promises_validated + (use "git restore ..." to discard changes in working directory) deleted: cfe_internal/CFE_cfengine.cf - deleted: cfe_internal/CFE_hub_specific.cf - deleted: cfe_internal/CFE_knowledge.cf - deleted: cfe_internal/cfengine_processes.cf - deleted: cfe_internal/ha/ha.cf - deleted: cfe_internal/ha/ha_def.cf - deleted: cfe_internal/host_info_report.cf - deleted: controls/3.4/cf_serverd.cf + deleted: cfe_internal/core/deprecated/cfengine_processes.cf + deleted: cfe_internal/core/host_info_report.cf + deleted: cfe_internal/core/limit_robot_agents.cf + deleted: cfe_internal/core/log_rotation.cf + deleted: cfe_internal/core/main.cf + deleted: cfe_internal/core/watchdog/templates/watchdog-windows.ps1.mustache + deleted: cfe_internal/core/watchdog/templates/watchdog.mustache + deleted: cfe_internal/core/watchdog/watchdog.cf + deleted: cfe_internal/enterprise/CFE_hub_specific.cf + deleted: cfe_internal/enterprise/CFE_knowledge.cf + deleted: cfe_internal/enterprise/federation/federation.cf + deleted: cfe_internal/enterprise/file_change.cf + deleted: cfe_internal/enterprise/ha/ha.cf + deleted: cfe_internal/enterprise/ha/ha_def.cf + deleted: cfe_internal/enterprise/ha/ha_update.cf + deleted: cfe_internal/enterprise/main.cf + deleted: cfe_internal/enterprise/mission_portal.cf + deleted: cfe_internal/enterprise/templates/httpd.conf.mustache + deleted: cfe_internal/enterprise/templates/runalerts.php.mustache + deleted: cfe_internal/enterprise/templates/runalerts.sh.mustache + deleted: cfe_internal/recommendations.cf + deleted: cfe_internal/update/cfe_internal_dc_workflow.cf + deleted: cfe_internal/update/cfe_internal_update_from_repository.cf + deleted: cfe_internal/update/lib.cf + deleted: cfe_internal/update/systemd_units.cf + deleted: cfe_internal/update/update_bins.cf + deleted: cfe_internal/update/update_policy.cf + deleted: cfe_internal/update/update_processes.cf + deleted: cfe_internal/update/windows_unattended_upgrade.cf deleted: controls/cf_agent.cf deleted: controls/cf_execd.cf deleted: controls/cf_hub.cf deleted: controls/cf_monitord.cf deleted: controls/cf_runagent.cf deleted: controls/cf_serverd.cf - deleted: def.cf + deleted: controls/def.cf + deleted: controls/def_inputs.cf + deleted: controls/reports.cf + deleted: controls/update_def.cf + deleted: controls/update_def_inputs.cf + deleted: custom-2.cf + deleted: def.json + deleted: inventory/aix.cf deleted: inventory/any.cf deleted: inventory/debian.cf + deleted: inventory/freebsd.cf deleted: inventory/generic.cf deleted: inventory/linux.cf deleted: inventory/lsb.cf @@ -170,724 +146,905 @@ Changes not staged for commit: deleted: inventory/redhat.cf deleted: inventory/suse.cf deleted: inventory/windows.cf - deleted: lib/3.5/bundles.cf - deleted: lib/3.5/cfe_internal.cf - deleted: lib/3.5/commands.cf - deleted: lib/3.5/common.cf - deleted: lib/3.5/databases.cf - deleted: lib/3.5/feature.cf - deleted: lib/3.5/files.cf - deleted: lib/3.5/guest_environments.cf - deleted: lib/3.5/monitor.cf - deleted: lib/3.5/packages.cf - deleted: lib/3.5/paths.cf - deleted: lib/3.5/processes.cf - deleted: lib/3.5/reports.cf - deleted: lib/3.5/services.cf - deleted: lib/3.5/storage.cf - deleted: lib/3.6/bundles.cf - deleted: lib/3.6/cfe_internal.cf - deleted: lib/3.6/cfengine_enterprise_hub_ha.cf - deleted: lib/3.6/commands.cf - deleted: lib/3.6/common.cf - deleted: lib/3.6/databases.cf - deleted: lib/3.6/edit_xml.cf - deleted: lib/3.6/examples.cf - deleted: lib/3.6/feature.cf - deleted: lib/3.6/files.cf - deleted: lib/3.6/guest_environments.cf - deleted: lib/3.6/monitor.cf - deleted: lib/3.6/packages.cf - deleted: lib/3.6/paths.cf - deleted: lib/3.6/processes.cf - deleted: lib/3.6/reports.cf - deleted: lib/3.6/services.cf - deleted: lib/3.6/stdlib.cf - deleted: lib/3.6/storage.cf - deleted: lib/3.6/users.cf - deleted: lib/3.6/vcs.cf + deleted: lib/autorun.cf + deleted: lib/bundles.cf + deleted: lib/cfe_internal.cf + deleted: lib/cfe_internal_hub.cf + deleted: lib/cfengine_enterprise_hub_ha.cf + deleted: lib/commands.cf + deleted: lib/common.cf + deleted: lib/databases.cf + deleted: lib/deprecated-upstream.cf + deleted: lib/edit_xml.cf + deleted: lib/event.cf + deleted: lib/examples.cf + deleted: lib/feature.cf + deleted: lib/files.cf + deleted: lib/guest_environments.cf + deleted: lib/monitor.cf + deleted: lib/packages-ENT-3719.cf + deleted: lib/packages.cf + deleted: lib/paths.cf + deleted: lib/processes.cf + deleted: lib/reports.cf + deleted: lib/services.cf + deleted: lib/stdlib.cf + deleted: lib/storage.cf + deleted: lib/testing.cf + deleted: lib/users.cf + deleted: lib/vcs.cf + deleted: modules/packages/vendored/WiRunSQL.vbs.mustache + deleted: modules/packages/vendored/apk.mustache + deleted: modules/packages/vendored/apt_get.mustache + deleted: modules/packages/vendored/freebsd_ports.mustache + deleted: modules/packages/vendored/msiexec-list.vbs.mustache + deleted: modules/packages/vendored/msiexec.bat.mustache + deleted: modules/packages/vendored/nimclient.mustache + deleted: modules/packages/vendored/pkg.mustache + deleted: modules/packages/vendored/pkgsrc.mustache + deleted: modules/packages/vendored/slackpkg.mustache + deleted: modules/packages/vendored/snap.mustache + deleted: modules/packages/vendored/yum.mustache + deleted: modules/packages/vendored/zypper.mustache deleted: promises.cf - deleted: services/autorun.cf - deleted: services/autorun/custom_policy2.cf + deleted: services/autorun/custom-1.cf deleted: services/autorun/hello.cf - deleted: services/file_change.cf - deleted: sketches/meta/api-runfile.cf + deleted: services/custom-3.cf + deleted: services/init.cf + deleted: services/main.cf + deleted: standalone_self_upgrade.cf + deleted: templates/cf-apache.service.mustache + deleted: templates/cf-execd.service.mustache + deleted: templates/cf-hub.service.mustache + deleted: templates/cf-monitord.service.mustache + deleted: templates/cf-postgres.service.mustache + deleted: templates/cf-runalerts.service.mustache + deleted: templates/cf-serverd.service.mustache + deleted: templates/cfengine3.service.mustache + deleted: templates/cfengine_watchdog.mustache + deleted: templates/federated_reporting/10-base_filter.sed + deleted: templates/federated_reporting/50-merge_inserts.awk + deleted: templates/federated_reporting/config.sh.mustache + deleted: templates/federated_reporting/dump.sh + deleted: templates/federated_reporting/import.sh + deleted: templates/federated_reporting/import_file.sh + deleted: templates/federated_reporting/log.sh.mustache + deleted: templates/federated_reporting/parallel.sh + deleted: templates/federated_reporting/psql_wrapper.sh.mustache + deleted: templates/federated_reporting/pull_dumps_from.sh + deleted: templates/federated_reporting/transport.sh deleted: templates/host_info_report.mustache + deleted: templates/json_multiline.mustache + deleted: templates/json_serial.mustache + deleted: templates/vercmp.ps1 deleted: update.cf - deleted: update/cfe_internal_dc_workflow.cf - deleted: update/cfe_internal_local_git_remote.cf - deleted: update/cfe_internal_update_from_repository.cf - deleted: update/update_bins.cf - deleted: update/update_policy.cf - deleted: update/update_processes.cf no changes added to commit (use "git add" and/or "git commit -a") ``` -## Install the new MPF -The MPF can be obtained from -any [community package](https://cfengine.com/product/community/) (in -```$(sys.workdir)/share/CoreBase/```), -[enterprise hub package](https://cfengine.com/product/free-download/) (in -```$(sys.workdir)/share/NovaBase/```), -[masterfiles source tarball](https://cfengine-package-repos.s3.amazonaws.com/tarballs/cfengine-masterfiles-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}.tar.gz) (requires -```./configure``` and ```make install``` -), -[installed masterfiles tarball](https://cfengine-package-repos.s3.amazonaws.com/tarballs/cfengine-masterfiles-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}.pkg.tar.gz) (ready -for extraction), -or -[directly from github](https://github.com/cfengine/masterfiles/tree/{{site.cfengine.masterfiles_branch}}). -We will install the MPF from source obtained -directly from github. -**Note:** You will need ```automake``` to install from source. +## Install the new version of the MPF -First clone the masterfiles repository for the version you are installing. And -verify you have the correct tag checked out. -**Note:** Directly checking out a tag as in the example below is only -supported in Git versions 1.7.9.5 and newer. -```console -[root@hub MPF_upgrade]# cd .. -[root@hub ~]# git clone -b 3.7.4 https://github.com/cfengine/masterfiles -[root@hub ~]# cd masterfiles -[root@hub ~]# git describe -3.7.4 -``` -**Note:** For systems without python 3 easily available (such as centos 6) you can use the following to get around problems in autogen with 3rdparty/core/determine-version.py, which requires python3. +### Installing from Git +First, clone the desired version of the MPF source. + +```bash +export MPF_VERSION="3.21.2" +git clone -b $MPF_VERSION https://github.com/cfengine/masterfiles $INTEGRATION_ROOT/masterfiles-source-$MPF_VERSION ``` -export EXPLICIT_VERSION=$(git describe) +```output +Cloning into '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2'... +Note: switching to 'f495603285f9bd90d5d36df4fec4870aeee751e8'. + +You are in 'detached HEAD' state. You can look around, make experimental +changes and commit them, and you can discard any commits you make in this +state without impacting any branches by switching back to a branch. + +If you want to create a new branch to retain commits you create, you may +do so (now or later) by using -c with the switch command. Example: + + git switch -c + +Or undo this operation with: + + git switch - + +Turn off this advice by setting config variable advice.detachedHead to false ``` -Now we will install the masterfiles from upstream into the directory where we -are doing the integration. +Then build and install targeting the integration root directory. When installed from source masterfiles installs into the `masterfiles` directory. -First we build and install masterfiles to a temporary location. +```bash +cd $INTEGRATION_ROOT/masterfiles-source-$MPF_VERSION +export EXPLICIT_VERSION=$MPF_VERSION -```console ./autogen.sh -[root@hub masterfiles]# ./autogen.sh -configure.ac:31: installing `./config.guess' -configure.ac:31: installing `./config.sub' -configure.ac:34: installing `./install-sh' -configure.ac:34: installing `./missing' -checking build system type... x86_64-unknown-linux-gnu -checking host system type... x86_64-unknown-linux-gnu -checking target system type... x86_64-unknown-linux-gnu +make +make install prefix=$INTEGRATION_ROOT/ +``` +```output +./autogen.sh: Running determine-version.sh ... +./autogen.sh: Running determine-release.sh ... +All tags pointing to current commit: +3.21.2 +3.21.2-build4 +Latest version: 3.21.2 +Could not parse it, using default release number 1 +./autogen.sh: Running autoreconf ... +configure.ac:40: installing './config.guess' +configure.ac:40: installing './config.sub' +configure.ac:43: installing './install-sh' +configure.ac:43: installing './missing' +parallel-tests: installing './test-driver' +/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2 +checking build system type... x86_64-pc-linux-gnu +checking host system type... x86_64-pc-linux-gnu +checking target system type... x86_64-pc-linux-gnu checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes -checking for a thread-safe mkdir -p... /bin/mkdir -p +checking for a race-free mkdir -p... /usr/bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes +checking whether make supports nested variables... yes +checking whether UID '1000' is supported by ustar format... yes +checking whether GID '1000' is supported by ustar format... yes checking how to create a ustar tar archive... gnutar -checking whether to disable maintainer-specific portions of Makefiles... yes -checking for a thread-safe mkdir -p... /bin/mkdir -p -checking for a BSD-compatible install... /usr/bin/install -c - -Summary of options: +checking if GNU tar supports --hard-dereference... yes +checking whether to enable maintainer-specific portions of Makefiles... yes +checking whether make supports nested variables... (cached) yes +checking for pkg_install... no +checking for shunit2... no + +Summary: +Version -> 3.21.2 +Release -> 1 Core directory -> not set - tests are disabled Enterprise directory -> not set - some tests are disabled Install prefix -> /var/cfengine +bindir -> /var/cfengine/bin configure: generating makefile targets +checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating Makefile -config.status: creating controls/3.5/update_def.cf -config.status: creating controls/3.6/update_def.cf -config.status: creating controls/3.7/update_def.cf -config.status: creating modules/packages/Makefile +config.status: creating controls/update_def.cf config.status: creating promises.cf +config.status: creating standalone_self_upgrade.cf +config.status: creating tests/Makefile config.status: creating tests/acceptance/Makefile config.status: creating tests/unit/Makefile DONE: Configuration done. Run "make install" to install CFEngine Masterfiles. -[root@hub masterfiles]# ./configure --prefix /tmp/masterfiles-3.7.4 -checking build system type... x86_64-unknown-linux-gnu -checking host system type... x86_64-unknown-linux-gnu -checking target system type... x86_64-unknown-linux-gnu -checking for a BSD-compatible install... /usr/bin/install -c -checking whether build environment is sane... yes -checking for a thread-safe mkdir -p... /bin/mkdir -p -checking for gawk... gawk -checking whether make sets $(MAKE)... yes -checking how to create a ustar tar archive... gnutar -checking whether to disable maintainer-specific portions of Makefiles... yes -checking for a thread-safe mkdir -p... /bin/mkdir -p -checking for a BSD-compatible install... /usr/bin/install -c -Summary of options: -Core directory -> not set - tests are disabled -Enterprise directory -> not set - some tests are disabled -Install prefix -> /tmp/masterfiles-3.7.4 +Making all in tests/ +make[1]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +Making all in . +make[2]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +make[2]: Nothing to be done for 'all-am'. +make[2]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +Making all in unit +make[2]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests/unit' +make[2]: Nothing to be done for 'all'. +make[2]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests/unit' +make[1]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +make[1]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2' +make[1]: Nothing to be done for 'all-am'. +make[1]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2' +Making install in tests/ +make[1]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +Making install in . +make[2]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +make[3]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +make[3]: Nothing to be done for 'install-exec-am'. +make[3]: Nothing to be done for 'install-data-am'. +make[3]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +make[2]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +Making install in unit +make[2]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests/unit' +make[3]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests/unit' +make[3]: Nothing to be done for 'install-exec-am'. +make[3]: Nothing to be done for 'install-data-am'. +make[3]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests/unit' +make[2]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests/unit' +make[1]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2/tests' +make[1]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2' +make[2]: Entering directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2' +make[2]: Nothing to be done for 'install-exec-am'. + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core' + /usr/bin/install -c -m 644 ./cfe_internal/core/host_info_report.cf ./cfe_internal/core/log_rotation.cf ./cfe_internal/core/main.cf ./cfe_internal/core/limit_robot_agents.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise/templates' + /usr/bin/install -c -m 644 ./cfe_internal/enterprise/templates/runalerts.sh.mustache ./cfe_internal/enterprise/templates/httpd.conf.mustache ./cfe_internal/enterprise/templates/apachectl.mustache ./cfe_internal/enterprise/templates/runalerts.php.mustache '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise/templates' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/inventory' + /usr/bin/install -c -m 644 ./inventory/windows.cf ./inventory/suse.cf ./inventory/macos.cf ./inventory/lsb.cf ./inventory/any.cf ./inventory/os.cf ./inventory/freebsd.cf ./inventory/generic.cf ./inventory/debian.cf ./inventory/linux.cf ./inventory/redhat.cf ./inventory/aix.cf '/tmp/MPF-upgrade/integration//masterfiles/inventory' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise/federation' + /usr/bin/install -c -m 644 ./cfe_internal/enterprise/federation/federation.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise/federation' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core/deprecated' + /usr/bin/install -c -m 644 ./cfe_internal/core/deprecated/cfengine_processes.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core/deprecated' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/lib/templates' + /usr/bin/install -c -m 644 ./lib/templates/tap.mustache ./lib/templates/junit.mustache '/tmp/MPF-upgrade/integration//masterfiles/lib/templates' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/services/autorun' + /usr/bin/install -c -m 644 ./services/autorun/hello.cf '/tmp/MPF-upgrade/integration//masterfiles/services/autorun' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/lib' + /usr/bin/install -c -m 644 ./lib/testing.cf ./lib/examples.cf ./lib/packages.cf ./lib/common.cf ./lib/users.cf ./lib/guest_environments.cf ./lib/cfengine_enterprise_hub_ha.cf ./lib/edit_xml.cf ./lib/files.cf ./lib/bundles.cf ./lib/reports.cf ./lib/event.cf ./lib/storage.cf ./lib/paths.cf ./lib/vcs.cf ./lib/stdlib.cf ./lib/autorun.cf ./lib/databases.cf ./lib/feature.cf ./lib/cfe_internal_hub.cf ./lib/monitor.cf ./lib/services.cf ./lib/packages-ENT-3719.cf ./lib/commands.cf ./lib/processes.cf ./lib/cfe_internal.cf '/tmp/MPF-upgrade/integration//masterfiles/lib' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/update' + /usr/bin/install -c -m 644 ./cfe_internal/update/cfe_internal_dc_workflow.cf ./cfe_internal/update/lib.cf ./cfe_internal/update/update_processes.cf ./cfe_internal/update/windows_unattended_upgrade.cf ./cfe_internal/update/systemd_units.cf ./cfe_internal/update/update_policy.cf ./cfe_internal/update/update_bins.cf ./cfe_internal/update/cfe_internal_update_from_repository.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/update' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/controls' + /usr/bin/install -c -m 644 ./controls/cf_agent.cf ./controls/cf_runagent.cf ./controls/cf_execd.cf ./controls/def_inputs.cf ./controls/cf_monitord.cf ./controls/def.cf ./controls/reports.cf ./controls/update_def_inputs.cf ./controls/cf_serverd.cf ./controls/cf_hub.cf ./controls/update_def.cf '/tmp/MPF-upgrade/integration//masterfiles/controls' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise/ha' + /usr/bin/install -c -m 644 ./cfe_internal/enterprise/ha/ha_def.cf ./cfe_internal/enterprise/ha/ha.cf ./cfe_internal/enterprise/ha/ha_update.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise/ha' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/modules/packages/vendored' + /usr/bin/install -c -m 644 ./modules/packages/vendored/apk.mustache ./modules/packages/vendored/msiexec.bat.mustache ./modules/packages/vendored/nimclient.mustache ./modules/packages/vendored/snap.mustache ./modules/packages/vendored/yum.mustache ./modules/packages/vendored/msiexec-list.vbs.mustache ./modules/packages/vendored/apt_get.mustache ./modules/packages/vendored/slackpkg.mustache ./modules/packages/vendored/pkgsrc.mustache ./modules/packages/vendored/pkg.mustache ./modules/packages/vendored/freebsd_ports.mustache ./modules/packages/vendored/zypper.mustache ./modules/packages/vendored/WiRunSQL.vbs.mustache '/tmp/MPF-upgrade/integration//masterfiles/modules/packages/vendored' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal' + /usr/bin/install -c -m 644 ./cfe_internal/recommendations.cf ./cfe_internal/CFE_cfengine.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal' + /usr/bin/install -c -m 644 ./update.cf ./promises.cf ./standalone_self_upgrade.cf '/tmp/MPF-upgrade/integration//masterfiles/.' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core/watchdog' + /usr/bin/install -c -m 644 ./cfe_internal/core/watchdog/watchdog.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core/watchdog' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core/watchdog/templates' + /usr/bin/install -c -m 644 ./cfe_internal/core/watchdog/templates/watchdog-windows.ps1.mustache ./cfe_internal/core/watchdog/templates/watchdog.mustache '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/core/watchdog/templates' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/templates' + /usr/bin/install -c -m 644 ./templates/cf-execd.service.mustache ./templates/cf-apache.service.mustache ./templates/host_info_report.mustache ./templates/cf-monitord.service.mustache ./templates/json_serial.mustache ./templates/json_multiline.mustache ./templates/cf-hub.service.mustache ./templates/cfengine3.service.mustache ./templates/cf-postgres.service.mustache ./templates/cfengine_watchdog.mustache ./templates/vercmp.ps1 ./templates/cf-runalerts.service.mustache ./templates/cf-serverd.service.mustache ./templates/cf-reactor.service.mustache '/tmp/MPF-upgrade/integration//masterfiles/templates' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise' + /usr/bin/install -c -m 644 ./cfe_internal/enterprise/CFE_knowledge.cf ./cfe_internal/enterprise/file_change.cf ./cfe_internal/enterprise/CFE_hub_specific.cf ./cfe_internal/enterprise/mission_portal.cf ./cfe_internal/enterprise/main.cf '/tmp/MPF-upgrade/integration//masterfiles/cfe_internal/enterprise' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/templates/federated_reporting' + /usr/bin/install -c -m 644 ./templates/federated_reporting/cfsecret.py ./templates/federated_reporting/import_file.sh ./templates/federated_reporting/psql_wrapper.sh.mustache ./templates/federated_reporting/import.sh ./templates/federated_reporting/transfer_distributed_cleanup_items.sh ./templates/federated_reporting/config.sh.mustache ./templates/federated_reporting/distributed_cleanup.py ./templates/federated_reporting/transport.sh ./templates/federated_reporting/log.sh.mustache ./templates/federated_reporting/dump.sh ./templates/federated_reporting/10-base_filter.sed ./templates/federated_reporting/nova_api.py ./templates/federated_reporting/pull_dumps_from.sh ./templates/federated_reporting/50-merge_inserts.awk ./templates/federated_reporting/parallel.sh '/tmp/MPF-upgrade/integration//masterfiles/templates/federated_reporting' + /usr/bin/mkdir -p '/tmp/MPF-upgrade/integration//masterfiles/services' + /usr/bin/install -c -m 644 ./services/init.cf ./services/main.cf '/tmp/MPF-upgrade/integration//masterfiles/services' +make[2]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2' +make[1]: Leaving directory '/tmp/MPF-upgrade/integration/masterfiles-source-3.21.2' +``` -configure: generating makefile targets -configure: creating ./config.status -config.status: creating Makefile -config.status: creating controls/3.5/update_def.cf -config.status: creating controls/3.6/update_def.cf -config.status: creating controls/3.7/update_def.cf -config.status: creating modules/packages/Makefile -config.status: creating promises.cf -config.status: creating tests/acceptance/Makefile -config.status: creating tests/unit/Makefile +We no longer need the source, we can clean it up. -DONE: Configuration done. Run "make install" to install CFEngine Masterfiles. +```bash +cd $INTEGRATION_ROOT/ +rm -rf $INTEGRATION_ROOT/masterfiles-source-$MPF_VERSION ``` -Then after running `make install` we move the installed masterfiles into our -integration directory. -```console -[root@hub masterfiles]# mv /tmp/masterfiles-3.7.4/masterfiles/* ../MPF_upgrade -[root@hub masterfiles]# cd ../MPF_upgrade/ -``` + ## Merge differences -Now we can use `git status` to see an overview of the changes to the -repository between our starting point and the new MPF. +Now we can use `git status` to see an overview of the changes to the repository between our starting point and the new MPF. -```console -[root@hub MPF_upgrade]# git status +```bash +cd $INTEGRATION_ROOT/masterfiles +git status +``` +```output On branch master Changes not staged for commit: (use "git add/rm ..." to update what will be committed) - (use "git checkout -- ..." to discard changes in working directory) - - deleted: CUSTOM/policy1.cf - deleted: cf_promises_release_id - deleted: cf_promises_validated - modified: cfe_internal/CFE_cfengine.cf - deleted: cfe_internal/CFE_hub_specific.cf - deleted: cfe_internal/CFE_knowledge.cf - deleted: cfe_internal/cfengine_processes.cf - deleted: cfe_internal/ha/ha.cf - deleted: cfe_internal/ha/ha_def.cf - deleted: cfe_internal/host_info_report.cf - deleted: controls/3.4/cf_serverd.cf - deleted: controls/cf_agent.cf - deleted: controls/cf_execd.cf - deleted: controls/cf_hub.cf - deleted: controls/cf_monitord.cf - deleted: controls/cf_runagent.cf - deleted: controls/cf_serverd.cf - deleted: def.cf + (use "git restore ..." to discard changes in working directory) + modified: cfe_internal/core/watchdog/templates/watchdog.mustache + modified: cfe_internal/enterprise/CFE_hub_specific.cf + modified: cfe_internal/enterprise/CFE_knowledge.cf + modified: cfe_internal/enterprise/federation/federation.cf + modified: cfe_internal/enterprise/file_change.cf + modified: cfe_internal/enterprise/main.cf + modified: cfe_internal/enterprise/mission_portal.cf + modified: cfe_internal/enterprise/templates/httpd.conf.mustache + modified: cfe_internal/update/cfe_internal_dc_workflow.cf + modified: cfe_internal/update/cfe_internal_update_from_repository.cf + modified: cfe_internal/update/lib.cf + modified: cfe_internal/update/update_bins.cf + modified: cfe_internal/update/update_policy.cf + modified: cfe_internal/update/update_processes.cf + modified: cfe_internal/update/windows_unattended_upgrade.cf + modified: controls/cf_agent.cf + modified: controls/cf_execd.cf + modified: controls/cf_serverd.cf + modified: controls/def.cf + modified: controls/reports.cf + modified: controls/update_def.cf + deleted: custom-2.cf + deleted: def.json modified: inventory/any.cf + modified: inventory/debian.cf modified: inventory/linux.cf - modified: inventory/lsb.cf - modified: lib/3.5/cfe_internal.cf - modified: lib/3.5/common.cf - modified: lib/3.5/files.cf - modified: lib/3.5/packages.cf - deleted: lib/3.5/reports.cf - modified: lib/3.6/cfe_internal.cf - modified: lib/3.6/common.cf - modified: lib/3.6/files.cf - modified: lib/3.6/packages.cf - deleted: lib/3.6/reports.cf - modified: lib/3.6/services.cf - modified: lib/3.6/stdlib.cf + modified: inventory/os.cf + modified: inventory/redhat.cf + modified: lib/autorun.cf + modified: lib/bundles.cf + modified: lib/cfe_internal_hub.cf + deleted: lib/deprecated-upstream.cf + modified: lib/files.cf + modified: lib/packages.cf + modified: lib/paths.cf + modified: lib/services.cf + modified: modules/packages/vendored/apt_get.mustache + modified: modules/packages/vendored/msiexec-list.vbs.mustache + modified: modules/packages/vendored/nimclient.mustache + modified: modules/packages/vendored/pkg.mustache + modified: modules/packages/vendored/zypper.mustache modified: promises.cf - deleted: services/autorun.cf - deleted: services/autorun/custom_policy2.cf - deleted: services/file_change.cf - modified: sketches/meta/api-runfile.cf + deleted: services/autorun/custom-1.cf + deleted: services/custom-3.cf + modified: services/main.cf + modified: standalone_self_upgrade.cf + modified: templates/cf-apache.service.mustache + modified: templates/cf-execd.service.mustache + modified: templates/cf-hub.service.mustache + modified: templates/cf-monitord.service.mustache + modified: templates/cf-postgres.service.mustache + modified: templates/cf-runalerts.service.mustache + modified: templates/cf-serverd.service.mustache + modified: templates/federated_reporting/config.sh.mustache + modified: templates/federated_reporting/dump.sh + modified: templates/federated_reporting/import.sh + modified: templates/federated_reporting/psql_wrapper.sh.mustache + modified: templates/federated_reporting/pull_dumps_from.sh modified: update.cf - deleted: update/cfe_internal_dc_workflow.cf - deleted: update/cfe_internal_local_git_remote.cf - deleted: update/cfe_internal_update_from_repository.cf - deleted: update/update_bins.cf - deleted: update/update_policy.cf - deleted: update/update_processes.cf Untracked files: (use "git add ..." to include in what will be committed) - - cfe_internal/core/ - cfe_internal/enterprise/ - cfe_internal/update/ - controls/3.5/ - controls/3.6/ - controls/3.7/ - inventory/freebsd.cf - lib/3.6/autorun.cf - lib/3.6/cfe_internal_hub.cf - lib/3.7/ - services/main.cf + cfe_internal/enterprise/templates/apachectl.mustache + lib/templates/ + templates/cf-reactor.service.mustache + templates/federated_reporting/cfsecret.py + templates/federated_reporting/distributed_cleanup.py + templates/federated_reporting/nova_api.py + templates/federated_reporting/transfer_distributed_cleanup_items.sh no changes added to commit (use "git add" and/or "git commit -a") ``` -All of the *Untracked files* are new additions from upstream so they should be -safe to take. - -```console -[root@hub MPF_upgrade]# git add cfe_internal/core/ \ -cfe_internal/enterprise/ \ -cfe_internal/update/ \ -controls/3.5/ \ -controls/3.6/ \ -controls/3.7/ \ -inventory/freebsd.cf \ -lib/3.6/autorun.cf \ -lib/3.6/cfe_internal_hub.cf \ -lib/3.7/ \ -services/main.cf +All of the **Untracked files** are new additions from upstream so they should be safe to take. + +```bash +git add cfe_internal/enterprise/templates/apachectl.mustache +git add lib/templates/junit.mustache +git add lib/templates/tap.mustache +git add templates/cf-reactor.service.mustache +git add templates/federated_reporting/cfsecret.py +git add templates/federated_reporting/distributed_cleanup.py +git add templates/federated_reporting/nova_api.py +git add templates/federated_reporting/transfer_distributed_cleanup_items.sh ``` We can run git status again to see the current overview: -```console -[root@hub MPF_upgrade]# git status +```command +git status +``` +```output On branch master Changes to be committed: - (use "git reset HEAD ..." to unstage) - - new file: cfe_internal/core/deprecated/cfengine_processes.cf - new file: cfe_internal/core/host_info_report.cf - new file: cfe_internal/core/limit_robot_agents.cf - new file: cfe_internal/core/log_rotation.cf - new file: cfe_internal/core/main.cf - new file: cfe_internal/enterprise/CFE_hub_specific.cf - new file: cfe_internal/enterprise/CFE_knowledge.cf - new file: cfe_internal/enterprise/file_change.cf - new file: cfe_internal/enterprise/ha/ha.cf - new file: cfe_internal/enterprise/ha/ha_def.cf - new file: cfe_internal/enterprise/ha/ha_update.cf - new file: cfe_internal/enterprise/main.cf - new file: cfe_internal/update/cfe_internal_dc_workflow.cf - new file: cfe_internal/update/cfe_internal_local_git_remote.cf - new file: cfe_internal/update/cfe_internal_update_from_repository.cf - new file: cfe_internal/update/update_bins.cf - new file: cfe_internal/update/update_policy.cf - new file: cfe_internal/update/update_processes.cf - new file: controls/3.5/cf_agent.cf - new file: controls/3.5/cf_execd.cf - new file: controls/3.5/cf_hub.cf - new file: controls/3.5/cf_monitord.cf - new file: controls/3.5/cf_runagent.cf - new file: controls/3.5/cf_serverd.cf - new file: controls/3.5/def.cf - new file: controls/3.5/def_inputs.cf - new file: controls/3.5/reports.cf - new file: controls/3.5/update_def.cf - new file: controls/3.5/update_def_inputs.cf - new file: controls/3.6/cf_agent.cf - new file: controls/3.6/cf_execd.cf - new file: controls/3.6/cf_hub.cf - new file: controls/3.6/cf_monitord.cf - new file: controls/3.6/cf_runagent.cf - new file: controls/3.6/cf_serverd.cf - new file: controls/3.6/def.cf - new file: controls/3.6/def_inputs.cf - new file: controls/3.6/reports.cf - new file: controls/3.6/update_def.cf - new file: controls/3.6/update_def_inputs.cf - new file: controls/3.7/cf_agent.cf - new file: controls/3.7/cf_execd.cf - new file: controls/3.7/cf_hub.cf - new file: controls/3.7/cf_monitord.cf - new file: controls/3.7/cf_runagent.cf - new file: controls/3.7/cf_serverd.cf - new file: controls/3.7/def.cf - new file: controls/3.7/def_inputs.cf - new file: controls/3.7/reports.cf - new file: controls/3.7/update_def.cf - new file: controls/3.7/update_def_inputs.cf - new file: inventory/freebsd.cf - new file: lib/3.6/autorun.cf - new file: lib/3.6/cfe_internal_hub.cf - new file: lib/3.7/autorun.cf - new file: lib/3.7/bundles.cf - new file: lib/3.7/cfe_internal.cf - new file: lib/3.7/cfe_internal_hub.cf - new file: lib/3.7/cfengine_enterprise_hub_ha.cf - new file: lib/3.7/commands.cf - new file: lib/3.7/common.cf - new file: lib/3.7/databases.cf - new file: lib/3.7/edit_xml.cf - new file: lib/3.7/examples.cf - new file: lib/3.7/feature.cf - new file: lib/3.7/files.cf - new file: lib/3.7/guest_environments.cf - new file: lib/3.7/monitor.cf - new file: lib/3.7/packages.cf - new file: lib/3.7/paths.cf - new file: lib/3.7/processes.cf - new file: lib/3.7/services.cf - new file: lib/3.7/stdlib.cf - new file: lib/3.7/storage.cf - new file: lib/3.7/users.cf - new file: lib/3.7/vcs.cf - new file: services/main.cf + (use "git restore --staged ..." to unstage) + new file: cfe_internal/enterprise/templates/apachectl.mustache + new file: lib/templates/junit.mustache + new file: lib/templates/tap.mustache + new file: templates/cf-reactor.service.mustache + new file: templates/federated_reporting/cfsecret.py + new file: templates/federated_reporting/distributed_cleanup.py + new file: templates/federated_reporting/nova_api.py + new file: templates/federated_reporting/transfer_distributed_cleanup_items.sh Changes not staged for commit: (use "git add/rm ..." to update what will be committed) - (use "git checkout -- ..." to discard changes in working directory) - - deleted: CUSTOM/policy1.cf - deleted: cf_promises_release_id - deleted: cf_promises_validated - modified: cfe_internal/CFE_cfengine.cf - deleted: cfe_internal/CFE_hub_specific.cf - deleted: cfe_internal/CFE_knowledge.cf - deleted: cfe_internal/cfengine_processes.cf - deleted: cfe_internal/ha/ha.cf - deleted: cfe_internal/ha/ha_def.cf - deleted: cfe_internal/host_info_report.cf - deleted: controls/3.4/cf_serverd.cf - deleted: controls/cf_agent.cf - deleted: controls/cf_execd.cf - deleted: controls/cf_hub.cf - deleted: controls/cf_monitord.cf - deleted: controls/cf_runagent.cf - deleted: controls/cf_serverd.cf - deleted: def.cf + (use "git restore ..." to discard changes in working directory) + modified: cfe_internal/core/watchdog/templates/watchdog.mustache + modified: cfe_internal/enterprise/CFE_hub_specific.cf + modified: cfe_internal/enterprise/CFE_knowledge.cf + modified: cfe_internal/enterprise/federation/federation.cf + modified: cfe_internal/enterprise/file_change.cf + modified: cfe_internal/enterprise/main.cf + modified: cfe_internal/enterprise/mission_portal.cf + modified: cfe_internal/enterprise/templates/httpd.conf.mustache + modified: cfe_internal/update/cfe_internal_dc_workflow.cf + modified: cfe_internal/update/cfe_internal_update_from_repository.cf + modified: cfe_internal/update/lib.cf + modified: cfe_internal/update/update_bins.cf + modified: cfe_internal/update/update_policy.cf + modified: cfe_internal/update/update_processes.cf + modified: cfe_internal/update/windows_unattended_upgrade.cf + modified: controls/cf_agent.cf + modified: controls/cf_execd.cf + modified: controls/cf_serverd.cf + modified: controls/def.cf + modified: controls/reports.cf + modified: controls/update_def.cf + deleted: custom-2.cf + deleted: def.json modified: inventory/any.cf + modified: inventory/debian.cf modified: inventory/linux.cf - modified: inventory/lsb.cf - modified: lib/3.5/cfe_internal.cf - modified: lib/3.5/common.cf - modified: lib/3.5/files.cf - modified: lib/3.5/packages.cf - deleted: lib/3.5/reports.cf - modified: lib/3.6/cfe_internal.cf - modified: lib/3.6/common.cf - modified: lib/3.6/files.cf - modified: lib/3.6/packages.cf - deleted: lib/3.6/reports.cf - modified: lib/3.6/services.cf - modified: lib/3.6/stdlib.cf + modified: inventory/os.cf + modified: inventory/redhat.cf + modified: lib/autorun.cf + modified: lib/bundles.cf + modified: lib/cfe_internal_hub.cf + deleted: lib/deprecated-upstream.cf + modified: lib/files.cf + modified: lib/packages.cf + modified: lib/paths.cf + modified: lib/services.cf + modified: modules/packages/vendored/apt_get.mustache + modified: modules/packages/vendored/msiexec-list.vbs.mustache + modified: modules/packages/vendored/nimclient.mustache + modified: modules/packages/vendored/pkg.mustache + modified: modules/packages/vendored/zypper.mustache modified: promises.cf - deleted: services/autorun.cf - deleted: services/autorun/custom_policy2.cf - deleted: services/file_change.cf - modified: sketches/meta/api-runfile.cf + deleted: services/autorun/custom-1.cf + deleted: services/custom-3.cf + modified: services/main.cf + modified: standalone_self_upgrade.cf + modified: templates/cf-apache.service.mustache + modified: templates/cf-execd.service.mustache + modified: templates/cf-hub.service.mustache + modified: templates/cf-monitord.service.mustache + modified: templates/cf-postgres.service.mustache + modified: templates/cf-runalerts.service.mustache + modified: templates/cf-serverd.service.mustache + modified: templates/federated_reporting/config.sh.mustache + modified: templates/federated_reporting/dump.sh + modified: templates/federated_reporting/import.sh + modified: templates/federated_reporting/psql_wrapper.sh.mustache + modified: templates/federated_reporting/pull_dumps_from.sh modified: update.cf - deleted: update/cfe_internal_dc_workflow.cf - deleted: update/cfe_internal_local_git_remote.cf - deleted: update/cfe_internal_update_from_repository.cf - deleted: update/update_bins.cf - deleted: update/update_policy.cf - deleted: update/update_processes.cf ``` -Next we want to bring back any of our custom policy files. Keeping your -polices organized together helps to make this process easy. The custom policy -files in the example policy set are `CUSTOM/policy1.cf` and -`services/autorun/custom_policy2.cf`. Restore them with `git checkout`. +Next we want to bring back any of our custom files. Look through the **deleted** files, identify your custom files and restore them with `git checkout`. -```console -[root@hub MPF_upgrade] git checkout CUSTOM/policy1.cf services/autorun/custom_policy2.cf +```command +git ls-files --deleted ``` +```output +custom-2.cf +def.json +lib/deprecated-upstream.cf +services/autorun/custom-1.cf +services/custom-3.cf +``` + +Keeping your polices organized together helps to make this process easy. The custom policy files in the example policy set are `def.json`, `services/autorun/custom-1.cf`, `custom-2.cf`, and `services/custom-3.cf`. -The files marked as *modified* in the `git status` output are files that have -changed upstream. +```bash +git checkout custom-2.cf +git checkout def.json +git checkout services/autorun/custom-1.cf +git checkout services/custom-3.cf +``` +```output +Updated 1 path from the index +Updated 1 path from the index +Updated 1 path from the index +Updated 1 path from the index +``` -```console -[root@hub MPF_upgrade]# git status | grep modified - modified: cfe_internal/CFE_cfengine.cf +Other deleted files from the upstream framework like `lib/deprecated-upstream.cf` should be deleted with `git rm`. + +**Note:** It is uncommon for any files to be moved or deleted between patch releases (e.g. `3.18.0` -> `3.18.5`) like `lib/deprecated-upstream.cf` in this example. + +```command +git rm lib/deprecated-upstream.cf +``` +```output +rm 'lib/deprecated-upstream.cf' +``` + +The files marked as **modified** in the `git status` output are files that have changed upstream. + +```command +git status +``` +```output +On branch master +Changes to be committed: + (use "git restore --staged ..." to unstage) + new file: cfe_internal/enterprise/templates/apachectl.mustache + deleted: lib/deprecated-upstream.cf + new file: lib/templates/junit.mustache + new file: lib/templates/tap.mustache + new file: templates/cf-reactor.service.mustache + new file: templates/federated_reporting/cfsecret.py + new file: templates/federated_reporting/distributed_cleanup.py + new file: templates/federated_reporting/nova_api.py + new file: templates/federated_reporting/transfer_distributed_cleanup_items.sh + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: cfe_internal/core/watchdog/templates/watchdog.mustache + modified: cfe_internal/enterprise/CFE_hub_specific.cf + modified: cfe_internal/enterprise/CFE_knowledge.cf + modified: cfe_internal/enterprise/federation/federation.cf + modified: cfe_internal/enterprise/file_change.cf + modified: cfe_internal/enterprise/main.cf + modified: cfe_internal/enterprise/mission_portal.cf + modified: cfe_internal/enterprise/templates/httpd.conf.mustache + modified: cfe_internal/update/cfe_internal_dc_workflow.cf + modified: cfe_internal/update/cfe_internal_update_from_repository.cf + modified: cfe_internal/update/lib.cf + modified: cfe_internal/update/update_bins.cf + modified: cfe_internal/update/update_policy.cf + modified: cfe_internal/update/update_processes.cf + modified: cfe_internal/update/windows_unattended_upgrade.cf + modified: controls/cf_agent.cf + modified: controls/cf_execd.cf + modified: controls/cf_serverd.cf + modified: controls/def.cf + modified: controls/reports.cf + modified: controls/update_def.cf modified: inventory/any.cf + modified: inventory/debian.cf modified: inventory/linux.cf - modified: inventory/lsb.cf - modified: lib/3.5/cfe_internal.cf - modified: lib/3.5/common.cf - modified: lib/3.5/files.cf - modified: lib/3.5/packages.cf - modified: lib/3.6/cfe_internal.cf - modified: lib/3.6/common.cf - modified: lib/3.6/files.cf - modified: lib/3.6/packages.cf - modified: lib/3.6/services.cf - modified: lib/3.6/stdlib.cf + modified: inventory/os.cf + modified: inventory/redhat.cf + modified: lib/autorun.cf + modified: lib/bundles.cf + modified: lib/cfe_internal_hub.cf + modified: lib/files.cf + modified: lib/packages.cf + modified: lib/paths.cf + modified: lib/services.cf + modified: modules/packages/vendored/apt_get.mustache + modified: modules/packages/vendored/msiexec-list.vbs.mustache + modified: modules/packages/vendored/nimclient.mustache + modified: modules/packages/vendored/pkg.mustache + modified: modules/packages/vendored/zypper.mustache modified: promises.cf - modified: sketches/meta/api-runfile.cf + modified: services/main.cf + modified: standalone_self_upgrade.cf + modified: templates/cf-apache.service.mustache + modified: templates/cf-execd.service.mustache + modified: templates/cf-hub.service.mustache + modified: templates/cf-monitord.service.mustache + modified: templates/cf-postgres.service.mustache + modified: templates/cf-runalerts.service.mustache + modified: templates/cf-serverd.service.mustache + modified: templates/federated_reporting/config.sh.mustache + modified: templates/federated_reporting/dump.sh + modified: templates/federated_reporting/import.sh + modified: templates/federated_reporting/psql_wrapper.sh.mustache + modified: templates/federated_reporting/pull_dumps_from.sh modified: update.cf ``` -For any files that you have not modified (like those in lib) simply add them -to gits staging area with `git add`. Carefully review and merge or -re-integrate your custom changes on top of the upstream files. +It's best to review the diff of **each** modified file to understand the upstream changes as well as identify any local modifications that need to be retained. You should always keep a good record of any modifications made to vendored files to ensure that nothing is lost during future framework upgrades. -The remaining files in `git status` marked as *deleted* are files that have -been moved or removed from upstream. +For example, here the diff for `promises.cf` shows upstream changes but also highlights where the vendored policy had been customized to integrate a custom policy. -**NOTE:** It is uncommon for any files to be moved or deleted between patch -releases (e.g. 3.7.1 -> 3.7.2). +```command +git diff promises.cf +``` -```console -[root@hub MPF_upgrade]# git status | grep deleted - deleted: cf_promises_release_id - deleted: cf_promises_validated - deleted: cfe_internal/CFE_hub_specific.cf - deleted: cfe_internal/CFE_knowledge.cf - deleted: cfe_internal/cfengine_processes.cf - deleted: cfe_internal/ha/ha.cf - deleted: cfe_internal/ha/ha_def.cf - deleted: cfe_internal/host_info_report.cf - deleted: controls/3.4/cf_serverd.cf - deleted: controls/cf_agent.cf - deleted: controls/cf_execd.cf - deleted: controls/cf_hub.cf - deleted: controls/cf_monitord.cf - deleted: controls/cf_runagent.cf - deleted: controls/cf_serverd.cf - deleted: def.cf - deleted: lib/3.5/reports.cf - deleted: lib/3.6/reports.cf - deleted: services/autorun.cf - deleted: services/file_change.cf - deleted: update/cfe_internal_dc_workflow.cf - deleted: update/cfe_internal_local_git_remote.cf - deleted: update/cfe_internal_update_from_repository.cf - deleted: update/update_bins.cf - deleted: update/update_policy.cf - deleted: update/update_processes.cf -``` - -It's a good idea to review these files as some of them might have contained -modifications, especially `def.cf` and any files under `controls`. Always keep -track of the modifications you make to any of the files that ship with the -MPF. Make sure that any necessary customization's to the deleted files are -carried through to their new locations. - -Once the files are no longer needed you can `git rm` them. - -```console -[root@hub MPF_upgrade]# git rm def.cf cf_promises_release_id cf_promises_validated cfe_internal/CFE_hub_specific.cf cfe_internal/CFE_knowledge.cf cfe_internal/cfengine_processes.cf cfe_internal/ha/ha.cf cfe_internal/ha/ha_def.cf cfe_internal/host_info_report.cf controls/3.4/cf_serverd.cf controls/cf_agent.cf controls/cf_execd.cf controls/cf_hub.cf controls/cf_monitord.cf controls/cf_runagent.cf controls/cf_serverd.cf lib/3.5/reports.cf lib/3.6/reports.cf services/autorun.cf services/file_change.cf update/cfe_internal_dc_workflow.cf update/cfe_internal_local_git_remote.cf update/cfe_internal_update_from_repository.cf update/update_bins.cf update/update_policy.cf update/update_processes.cf -rm 'def.cf' -rm 'cf_promises_release_id' -rm 'cf_promises_validated' -rm 'cfe_internal/CFE_hub_specific.cf' -rm 'cfe_internal/CFE_knowledge.cf' -rm 'cfe_internal/cfengine_processes.cf' -rm 'cfe_internal/ha/ha.cf' -rm 'cfe_internal/ha/ha_def.cf' -rm 'cfe_internal/host_info_report.cf' -rm 'controls/3.4/cf_serverd.cf' -rm 'controls/cf_agent.cf' -rm 'controls/cf_execd.cf' -rm 'controls/cf_hub.cf' -rm 'controls/cf_monitord.cf' -rm 'controls/cf_runagent.cf' -rm 'controls/cf_serverd.cf' -rm 'lib/3.5/reports.cf' -rm 'lib/3.6/reports.cf' -rm 'services/autorun.cf' -rm 'services/file_change.cf' -rm 'update/cfe_internal_dc_workflow.cf' -rm 'update/cfe_internal_local_git_remote.cf' -rm 'update/cfe_internal_update_from_repository.cf' -rm 'update/update_bins.cf' -rm 'update/update_policy.cf' -rm 'update/update_processes.cf' -``` - -Review `git status` and make sure that the policy validates then commit your -changes. - -```console -[root@hub MPF_upgrade]# git status +Output: + +```diff +diff --git a/promises.cf b/promises.cf +index 15c0c40..4611098 100644 +--- a/promises.cf ++++ b/promises.cf +@@ -5,7 +5,7 @@ + # MIT Public License + # http://www.opensource.org/licenses/MIT + +-# Copyright 2021 Northern.tech AS ++# Copyright 2022 Northern.tech AS + + # Permission is hereby granted, free of charge, to any person obtaining a copy of + # this software and associated documentation files (the "Software"), to deal in +@@ -56,10 +56,9 @@ body common control + + # Agent bundle + cfe_internal_management, # See cfe_internal/CFE_cfengine.cf +- main, ++ mpf_main, + @(cfengine_enterprise_hub_ha.management_bundles), + @(def.bundlesequence_end), +-custom_2, + + }; + +@@ -86,35 +85,24 @@ custom_2, + @(services_autorun.inputs), + + "services/main.cf", +-"custom-2.cf", + }; + +- version => "CFEngine Promises.cf 3.18.0"; ++ version => "CFEngine Promises.cf 3.21.2"; + + # From 3.7 onwards there is a new package promise implementation using package + # modules in which you MUST provide package modules used to generate + # software inventory reports. You can also provide global default package module + # instead of specifying it in all package promises. +- (debian).!disable_inventory_package_refresh:: ++ (debian|redhat|centos|suse|sles|opensuse|amazon_linux).cfe_python_for_package_modules_supported.!disable_inventory_package_refresh:: + package_inventory => { $(package_module_knowledge.platform_default) }; + +- # We only define pacakge_invetory on redhat like systems that have a +- # python version that works with the package module. +- (redhat|centos|suse|sles|opensuse|amazon_linux).cfe_yum_package_module_supported.!disable_inventory_package_refresh:: +- package_inventory => { $(package_module_knowledge.platform_default) }; +- + (debian|redhat|suse|sles|opensuse|amazon_linux):: + package_module => $(package_module_knowledge.platform_default); + +- # CFEngine 3.12.2+ and 3.14+ have new package module on Windows +- windows.cfengine_3_12.!(cfengine_3_12_0|cfengine_3_12_1):: +- package_inventory => { $(package_module_knowledge.platform_default) }; +- package_module => $(package_module_knowledge.platform_default); +-@if minimum_version(3.14) + windows:: + package_inventory => { $(package_module_knowledge.platform_default) }; + package_module => $(package_module_knowledge.platform_default); +-@endif ++ + termux:: + package_module => $(package_module_knowledge.platform_default); + +@@ -127,6 +115,12 @@ custom_2, + ignore_missing_inputs => "$(def.control_common_ignore_missing_inputs)"; + + ++ control_common_tls_min_version_defined:: ++ tls_min_version => "$(default:def.control_common_tls_min_version)"; # See also: allowtlsversion in body server control ++ ++ control_common_tls_ciphers_defined:: ++ tls_ciphers => "$(default:def.control_common_tls_ciphers)"; # See also: allowciphers in body server control ++ + } + + bundle common inventory +@@ -136,8 +130,6 @@ bundle common inventory + # + # Inventory bundles are simply common bundles loaded before anything + # else in promises.cf +-# +-# Tested to work properly against 3.5.x + { + classes: + "other_unix_os" expression => "!(windows|macos|linux|freebsd|aix)"; +@@ -341,9 +333,7 @@ bundle common services_autorun + # added to inputs automatically. + { + vars: +- services_autorun:: +- "inputs" slist => { "$(sys.local_libdir)/autorun.cf" }; +- ++ services_autorun|services_autorun_inputs:: + "_default_autorun_input_dir" + string => "$(this.promise_dirname)/services/autorun"; + "_default_autorun_inputs" +@@ -360,23 +350,34 @@ bundle common services_autorun + "found_inputs" slist => { @(_default_autorun_inputs), + sort( getvalues(_extra_autorun_inputs), "lex") }; + +- "bundles" slist => { "autorun" }; # run loaded bundles +- +- !services_autorun:: ++ !(services_autorun|services_autorun_inputs|services_autorun_bundles):: + # If services_autorun is not enabled, then we should not extend inputs + # automatically. + "inputs" slist => { }; + "found_inputs" slist => {}; + "bundles" slist => { "services_autorun" }; # run self + ++ services_autorun|services_autorun_inputs|services_autorun_bundles:: ++ "inputs" slist => { "$(sys.local_libdir)/autorun.cf" }; ++ "bundles" slist => { "autorun" }; # run loaded bundles ++ + reports: + DEBUG|DEBUG_services_autorun:: + "DEBUG $(this.bundle): Services Autorun Disabled" +- if => "!services_autorun"; ++ if => "!(services_autorun|services_autorun_bundles|services_autorun_inputs)"; + + "DEBUG $(this.bundle): Services Autorun Enabled" + if => "services_autorun"; + ++ "DEBUG $(this.bundle): Services Autorun Bundles Enabled" ++ if => "services_autorun_bundles"; ++ ++ "DEBUG $(this.bundle): Services Autorun Inputs Enabled" ++ if => "services_autorun_inputs"; ++ ++ "DEBUG $(this.bundle): Services Autorun (Bundles & Inputs) Enabled" ++ if => "services_autorun_inputs.services_autorun_bundles"; ++ + "DEBUG $(this.bundle): adding input='$(inputs)'" + if => isvariable("inputs"); +``` + +Carefully review the diffs and merge or re-integrate your custom changes on top of the upstream files. If you identify changes to the vendored files consider re-integrating those changes in a way that does not modify vendored files, here for example we have migrated the integration of the custom policy to Augments (`def.json`). + +```command +git diff def.json +``` + +Output: + +```diff +diff --git a/def.json b/def.json +index a7b98e6..60a0ce1 100644 +--- a/def.json ++++ b/def.json +@@ -1,8 +1,11 @@ + { +- "inputs": [ "services/custom-3.cf" ], ++ "inputs": [ "custom-2.cf", "services/custom-3.cf" ], + "classes": { + "default:services_autorun": { + "class_expressions": [ "any::" ], + "comment": "We want to use the autorun functionality because it is convenient." +- } ++ }, ++ "vars":{ ++ "control_common_bundlesequence_end": [ "custom_2" ] ++ } + } +\ No newline at end of file +``` + +So, we now want to accept all the changes to `promises.cf` and `def.json`. + +```command +git add promises.cf def.json +``` + +If you are unsure if or how to integrate customizations without modifying vendored policy reach out to support for help. For any modified files that you have not customized simply stage them for commit with `git add`. + +```bash +git add cfe_internal/core/watchdog/templates/watchdog.mustache +git add cfe_internal/enterprise/CFE_hub_specific.cf +git add cfe_internal/enterprise/CFE_knowledge.cf +git add cfe_internal/enterprise/federation/federation.cf +git add cfe_internal/enterprise/file_change.cf +git add cfe_internal/enterprise/main.cf +git add cfe_internal/enterprise/mission_portal.cf +git add cfe_internal/enterprise/templates/httpd.conf.mustache +git add cfe_internal/update/cfe_internal_dc_workflow.cf +git add cfe_internal/update/cfe_internal_update_from_repository.cf +git add cfe_internal/update/lib.cf +git add cfe_internal/update/update_bins.cf +git add cfe_internal/update/update_policy.cf +git add cfe_internal/update/update_processes.cf +git add cfe_internal/update/windows_unattended_upgrade.cf +git add controls/cf_agent.cf +git add controls/cf_execd.cf +git add controls/cf_serverd.cf +git add controls/def.cf +git add controls/reports.cf +git add controls/update_def.cf +git add def.json +git add inventory/any.cf +git add inventory/debian.cf +git add inventory/linux.cf +git add inventory/os.cf +git add inventory/redhat.cf +git add lib/autorun.cf +git add lib/bundles.cf +git add lib/cfe_internal_hub.cf +git add lib/files.cf +git add lib/packages.cf +git add lib/paths.cf +git add lib/services.cf +git add modules/packages/vendored/apt_get.mustache +git add modules/packages/vendored/msiexec-list.vbs.mustache +git add modules/packages/vendored/nimclient.mustache +git add modules/packages/vendored/pkg.mustache +git add modules/packages/vendored/zypper.mustache +git add promises.cf +git add services/main.cf +git add standalone_self_upgrade.cf +git add templates/cf-apache.service.mustache +git add templates/cf-execd.service.mustache +git add templates/cf-hub.service.mustache +git add templates/cf-monitord.service.mustache +git add templates/cf-postgres.service.mustache +git add templates/cf-runalerts.service.mustache +git add templates/cf-serverd.service.mustache +git add templates/federated_reporting/config.sh.mustache +git add templates/federated_reporting/dump.sh +git add templates/federated_reporting/import.sh +git add templates/federated_reporting/psql_wrapper.sh.mustache +git add templates/federated_reporting/pull_dumps_from.sh +git add update.cf +``` + +Review `git status` one more time to make sure the changes are as expected. + +```command +git status +``` +```output On branch master Changes to be committed: - (use "git reset HEAD ..." to unstage) - - deleted: cf_promises_release_id - deleted: cf_promises_validated - modified: cfe_internal/CFE_cfengine.cf - renamed: cfe_internal/cfengine_processes.cf -> cfe_internal/core/deprecated/cfengine_processes.cf - renamed: cfe_internal/host_info_report.cf -> cfe_internal/core/host_info_report.cf - new file: cfe_internal/core/limit_robot_agents.cf - new file: cfe_internal/core/log_rotation.cf - new file: cfe_internal/core/main.cf - renamed: cfe_internal/CFE_hub_specific.cf -> cfe_internal/enterprise/CFE_hub_specific.cf - renamed: cfe_internal/CFE_knowledge.cf -> cfe_internal/enterprise/CFE_knowledge.cf - renamed: services/file_change.cf -> cfe_internal/enterprise/file_change.cf - new file: cfe_internal/enterprise/ha/ha.cf - renamed: cfe_internal/ha/ha_def.cf -> cfe_internal/enterprise/ha/ha_def.cf - new file: cfe_internal/enterprise/ha/ha_update.cf - new file: cfe_internal/enterprise/main.cf - deleted: cfe_internal/ha/ha.cf - renamed: update/cfe_internal_dc_workflow.cf -> cfe_internal/update/cfe_internal_dc_workflow.cf - renamed: update/cfe_internal_local_git_remote.cf -> cfe_internal/update/cfe_internal_local_git_remote.cf - new file: cfe_internal/update/cfe_internal_update_from_repository.cf - renamed: update/update_bins.cf -> cfe_internal/update/update_bins.cf - renamed: update/update_policy.cf -> cfe_internal/update/update_policy.cf - renamed: update/update_processes.cf -> cfe_internal/update/update_processes.cf - deleted: controls/3.4/cf_serverd.cf - renamed: controls/cf_agent.cf -> controls/3.5/cf_agent.cf - new file: controls/3.5/cf_execd.cf - renamed: controls/cf_hub.cf -> controls/3.5/cf_hub.cf - renamed: controls/cf_monitord.cf -> controls/3.5/cf_monitord.cf - renamed: controls/cf_runagent.cf -> controls/3.5/cf_runagent.cf - renamed: controls/cf_serverd.cf -> controls/3.5/cf_serverd.cf - renamed: def.cf -> controls/3.5/def.cf - new file: controls/3.5/def_inputs.cf - renamed: lib/3.5/reports.cf -> controls/3.5/reports.cf - renamed: update.cf -> controls/3.5/update_def.cf - new file: controls/3.5/update_def_inputs.cf - new file: controls/3.6/cf_agent.cf - new file: controls/3.6/cf_execd.cf - new file: controls/3.6/cf_hub.cf - new file: controls/3.6/cf_monitord.cf - new file: controls/3.6/cf_runagent.cf - new file: controls/3.6/cf_serverd.cf - new file: controls/3.6/def.cf - new file: controls/3.6/def_inputs.cf - renamed: lib/3.6/reports.cf -> controls/3.6/reports.cf - new file: controls/3.6/update_def.cf - new file: controls/3.6/update_def_inputs.cf - new file: controls/3.7/cf_agent.cf - new file: controls/3.7/cf_execd.cf - new file: controls/3.7/cf_hub.cf - new file: controls/3.7/cf_monitord.cf - new file: controls/3.7/cf_runagent.cf - new file: controls/3.7/cf_serverd.cf - new file: controls/3.7/def.cf - new file: controls/3.7/def_inputs.cf - new file: controls/3.7/reports.cf - new file: controls/3.7/update_def.cf - new file: controls/3.7/update_def_inputs.cf - deleted: controls/cf_execd.cf + (use "git restore --staged ..." to unstage) + modified: cfe_internal/core/watchdog/templates/watchdog.mustache + modified: cfe_internal/enterprise/CFE_hub_specific.cf + modified: cfe_internal/enterprise/CFE_knowledge.cf + modified: cfe_internal/enterprise/federation/federation.cf + modified: cfe_internal/enterprise/file_change.cf + modified: cfe_internal/enterprise/main.cf + modified: cfe_internal/enterprise/mission_portal.cf + new file: cfe_internal/enterprise/templates/apachectl.mustache + modified: cfe_internal/enterprise/templates/httpd.conf.mustache + modified: cfe_internal/update/cfe_internal_dc_workflow.cf + modified: cfe_internal/update/cfe_internal_update_from_repository.cf + modified: cfe_internal/update/lib.cf + modified: cfe_internal/update/update_bins.cf + modified: cfe_internal/update/update_policy.cf + modified: cfe_internal/update/update_processes.cf + modified: cfe_internal/update/windows_unattended_upgrade.cf + modified: controls/cf_agent.cf + modified: controls/cf_execd.cf + modified: controls/cf_serverd.cf + modified: controls/def.cf + modified: controls/reports.cf + modified: controls/update_def.cf + modified: def.json modified: inventory/any.cf - new file: inventory/freebsd.cf + modified: inventory/debian.cf modified: inventory/linux.cf - modified: inventory/lsb.cf - modified: lib/3.5/cfe_internal.cf - modified: lib/3.5/common.cf - modified: lib/3.5/files.cf - modified: lib/3.5/packages.cf - renamed: services/autorun.cf -> lib/3.6/autorun.cf - modified: lib/3.6/cfe_internal.cf - renamed: lib/3.6/cfe_internal.cf -> lib/3.6/cfe_internal_hub.cf - modified: lib/3.6/common.cf - modified: lib/3.6/files.cf - modified: lib/3.6/packages.cf - modified: lib/3.6/services.cf - modified: lib/3.6/stdlib.cf - new file: lib/3.7/autorun.cf - new file: lib/3.7/bundles.cf - new file: lib/3.7/cfe_internal.cf - new file: lib/3.7/cfe_internal_hub.cf - new file: lib/3.7/cfengine_enterprise_hub_ha.cf - new file: lib/3.7/commands.cf - new file: lib/3.7/common.cf - new file: lib/3.7/databases.cf - new file: lib/3.7/edit_xml.cf - new file: lib/3.7/examples.cf - new file: lib/3.7/feature.cf - new file: lib/3.7/files.cf - new file: lib/3.7/guest_environments.cf - new file: lib/3.7/monitor.cf - new file: lib/3.7/packages.cf - new file: lib/3.7/paths.cf - new file: lib/3.7/processes.cf - new file: lib/3.7/services.cf - new file: lib/3.7/stdlib.cf - new file: lib/3.7/storage.cf - new file: lib/3.7/users.cf - new file: lib/3.7/vcs.cf + modified: inventory/os.cf + modified: inventory/redhat.cf + modified: lib/autorun.cf + modified: lib/bundles.cf + modified: lib/cfe_internal_hub.cf + deleted: lib/deprecated-upstream.cf + modified: lib/files.cf + modified: lib/packages.cf + modified: lib/paths.cf + modified: lib/services.cf + new file: lib/templates/junit.mustache + new file: lib/templates/tap.mustache + modified: modules/packages/vendored/apt_get.mustache + modified: modules/packages/vendored/msiexec-list.vbs.mustache + modified: modules/packages/vendored/nimclient.mustache + modified: modules/packages/vendored/pkg.mustache + modified: modules/packages/vendored/zypper.mustache modified: promises.cf - new file: services/main.cf - modified: sketches/meta/api-runfile.cf + modified: services/main.cf + modified: standalone_self_upgrade.cf + modified: templates/cf-apache.service.mustache + modified: templates/cf-execd.service.mustache + modified: templates/cf-hub.service.mustache + modified: templates/cf-monitord.service.mustache + modified: templates/cf-postgres.service.mustache + new file: templates/cf-reactor.service.mustache + modified: templates/cf-runalerts.service.mustache + modified: templates/cf-serverd.service.mustache + new file: templates/federated_reporting/cfsecret.py + modified: templates/federated_reporting/config.sh.mustache + new file: templates/federated_reporting/distributed_cleanup.py + modified: templates/federated_reporting/dump.sh + modified: templates/federated_reporting/import.sh + new file: templates/federated_reporting/nova_api.py + modified: templates/federated_reporting/psql_wrapper.sh.mustache + modified: templates/federated_reporting/pull_dumps_from.sh + new file: templates/federated_reporting/transfer_distributed_cleanup_items.sh modified: update.cf - deleted: update/cfe_internal_update_from_repository.cf - -[root@hub MPF_upgrade]# cf-promises -cf ./promises.cf -[root@hub MPF_upgrade]# cf-promises -cf ./update.cf -[root@hub MPF_upgrade]# git commit -m "After Policy Upgrade" - 100 files changed, 12521 insertions(+), 1493 deletions(-) - delete mode 100644 cf_promises_release_id - delete mode 100644 cf_promises_validated - rewrite cfe_internal/CFE_cfengine.cf (88%) - rename cfe_internal/{ => core/deprecated}/cfengine_processes.cf (95%) - rename cfe_internal/{ => core}/host_info_report.cf (98%) - create mode 100644 cfe_internal/core/limit_robot_agents.cf - create mode 100644 cfe_internal/core/log_rotation.cf - create mode 100644 cfe_internal/core/main.cf - rename cfe_internal/{ => enterprise}/CFE_hub_specific.cf (85%) - rename cfe_internal/{ => enterprise}/CFE_knowledge.cf (100%) - rename {services => cfe_internal/enterprise}/file_change.cf (58%) - create mode 100644 cfe_internal/enterprise/ha/ha.cf - rename cfe_internal/{ => enterprise}/ha/ha_def.cf (54%) - create mode 100644 cfe_internal/enterprise/ha/ha_update.cf - create mode 100644 cfe_internal/enterprise/main.cf - delete mode 100644 cfe_internal/ha/ha.cf - rename {update => cfe_internal/update}/cfe_internal_dc_workflow.cf (100%) - rename {update => cfe_internal/update}/cfe_internal_local_git_remote.cf (100%) - create mode 100644 cfe_internal/update/cfe_internal_update_from_repository.cf - rename {update => cfe_internal/update}/update_bins.cf (97%) - rename {update => cfe_internal/update}/update_policy.cf (92%) - rename {update => cfe_internal/update}/update_processes.cf (92%) - delete mode 100644 controls/3.4/cf_serverd.cf - rename controls/{ => 3.5}/cf_agent.cf (80%) - create mode 100644 controls/3.5/cf_execd.cf - rename controls/{ => 3.5}/cf_hub.cf (100%) - rename controls/{ => 3.5}/cf_monitord.cf (100%) - rename controls/{ => 3.5}/cf_runagent.cf (100%) - rename controls/{ => 3.5}/cf_serverd.cf (87%) - rename def.cf => controls/3.5/def.cf (74%) - create mode 100644 controls/3.5/def_inputs.cf - rename {lib => controls}/3.5/reports.cf (80%) - rename update.cf => controls/3.5/update_def.cf (59%) - create mode 100644 controls/3.5/update_def_inputs.cf - create mode 100644 controls/3.6/cf_agent.cf - create mode 100644 controls/3.6/cf_execd.cf - create mode 100644 controls/3.6/cf_hub.cf - create mode 100644 controls/3.6/cf_monitord.cf - create mode 100644 controls/3.6/cf_runagent.cf - create mode 100644 controls/3.6/cf_serverd.cf - create mode 100644 controls/3.6/def.cf - create mode 100644 controls/3.6/def_inputs.cf - rename {lib => controls}/3.6/reports.cf (78%) - create mode 100644 controls/3.6/update_def.cf - create mode 100644 controls/3.6/update_def_inputs.cf - create mode 100644 controls/3.7/cf_agent.cf - create mode 100644 controls/3.7/cf_execd.cf - create mode 100644 controls/3.7/cf_hub.cf - create mode 100644 controls/3.7/cf_monitord.cf - create mode 100644 controls/3.7/cf_runagent.cf - create mode 100644 controls/3.7/cf_serverd.cf - create mode 100644 controls/3.7/def.cf - create mode 100644 controls/3.7/def_inputs.cf - create mode 100644 controls/3.7/reports.cf - create mode 100644 controls/3.7/update_def.cf - create mode 100644 controls/3.7/update_def_inputs.cf - delete mode 100644 controls/cf_execd.cf - create mode 100644 inventory/freebsd.cf - rename {services => lib/3.6}/autorun.cf (50%) - rewrite lib/3.6/cfe_internal.cf (67%) - rename lib/3.6/{cfe_internal.cf => cfe_internal_hub.cf} (77%) - create mode 100644 lib/3.7/autorun.cf - create mode 100644 lib/3.7/bundles.cf - create mode 100644 lib/3.7/cfe_internal.cf - create mode 100644 lib/3.7/cfe_internal_hub.cf - create mode 100644 lib/3.7/cfengine_enterprise_hub_ha.cf - create mode 100644 lib/3.7/commands.cf - create mode 100644 lib/3.7/common.cf - create mode 100644 lib/3.7/databases.cf - create mode 100644 lib/3.7/edit_xml.cf - create mode 100644 lib/3.7/examples.cf - create mode 100644 lib/3.7/feature.cf - create mode 100644 lib/3.7/files.cf - create mode 100644 lib/3.7/guest_environments.cf - create mode 100644 lib/3.7/monitor.cf - create mode 100644 lib/3.7/packages.cf - create mode 100644 lib/3.7/paths.cf - create mode 100644 lib/3.7/processes.cf - create mode 100644 lib/3.7/services.cf - create mode 100644 lib/3.7/stdlib.cf - create mode 100644 lib/3.7/storage.cf - create mode 100644 lib/3.7/users.cf - create mode 100644 lib/3.7/vcs.cf - create mode 100644 services/main.cf - rewrite update.cf (78%) - delete mode 100644 update/cfe_internal_update_from_repository.cf +``` + +Make sure the policy validates and commit your changes. + +```command +git commit -m "Upgraded MPF from 3.18.0 to 3.21.2" +``` +```output +[master a5d512c] Upgraded MPF from 3.18.0 to 3.21.2 + 64 files changed, 2599 insertions(+), 728 deletions(-) + create mode 100644 cfe_internal/enterprise/templates/apachectl.mustache + rewrite inventory/redhat.cf (63%) + delete mode 100644 lib/deprecated-upstream.cf + create mode 100644 lib/templates/junit.mustache + create mode 100644 lib/templates/tap.mustache + create mode 100644 templates/cf-reactor.service.mustache + create mode 100644 templates/federated_reporting/cfsecret.py + create mode 100644 templates/federated_reporting/distributed_cleanup.py + create mode 100644 templates/federated_reporting/nova_api.py + create mode 100644 templates/federated_reporting/transfer_distributed_cleanup_items.sh ``` Now your Masterfiles Policy Framework is upgraded and ready to be tested. diff --git a/examples/tutorials/nfs_and_containers.cf b/examples/tutorials/nfs_and_containers.cf deleted file mode 100644 index 6e5861a8b..000000000 --- a/examples/tutorials/nfs_and_containers.cf +++ /dev/null @@ -1,383 +0,0 @@ -body common control { - - inputs => { - "/var/cfengine/masterfiles/lib/3.6/stdlib.cf", - }; - -} - -bundle common global_vars -{ - vars: - - "host_ip" string => "10.100.100.129"; - "lxc_network" string => "192.168.122"; - "gateway_ip" string => "$(lxc_network).1"; - "container_ip" string => "$(lxc_network).101"; - "container_name" string => "cfe-centos-2"; - -} - -bundle agent remove_existing_items -{ - - commands: - "/usr/bin/lxc-stop -n $(globar_vars.container_name)"; - "/bin/rm -fr /root/3514296"; - "/bin/rm -fr /root/epel-release-6-8.noarch.rpm"; - "/bin/rm -fr /root/remi-release-6.rpm"; - "/bin/rm -fr /root/quick-install-cfengine-enterprise.sh"; - "/bin/rm -fr /var/lib/lxc/$(globar_vars.container_name)"; - "/bin/rm -fr /usr/share/lxc/templates/lxc-centos"; - - reports: - "This bundle ensures we are starting fresh. The command lines could be replaced by native CFEngine functionality."; - -} - -bundle agent change_service_state(service, state) -{ - - commands: - "/sbin/service $(service) $(state)"; - -} - - -bundle agent install_wget -{ - - # Shouldn't be necessary, but just in case - - vars: - - "match_package" slist => { - "wget" - }; - - packages: - "$(match_package)" - package_policy => "add", - package_method => yum; - - reports: - "Installing the wget package is done here using CFEngine's 'packages' promise type. The installation of wget may not be necessary in many cases, as it might already be installed."; - -} - -bundle agent get_cfe_script -{ - commands: - "/usr/bin/wget -nc -P /root https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh"; -} - -bundle agent install_ssh_server_and_client -{ - - vars: - - "match_package" slist => { - "openssh-server", - "openssh-clients" - }; - - packages: - "$(match_package)" - package_policy => "add", - package_method => yum; - -} - -bundle agent install_lxc -{ - - commands: - "/usr/bin/wget -nc -P /root http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm"; - "/usr/bin/wget -nc -P /root http://rpms.famillecollet.com/enterprise/remi-release-6.rpm"; - "/bin/rpm -Uvh /root/remi-release-6*.rpm /root/epel-release-6*.rpm"; - - vars: - - "match_package" slist => { - "lxc" - }; - - packages: - "$(match_package)" - package_policy => "add", - package_method => yum; - -} - -bundle agent install_git{ - - vars: - - "match_package" slist => { - "git" - }; - - packages: - "$(match_package)" - package_policy => "add", - package_method => yum; - -} - -bundle agent get_lxc_centos_template -{ - - commands: - "/usr/bin/git clone https://gist.github.com/3514296.git /root/3514296"; - "/bin/cp /root/3514296/lxc-centos /usr/share/lxc/templates/"; #This could be done with CFEngine native functionality as well - "/bin/chmod a+rx /usr/share/lxc/templates/lxc-centos"; - - reports: - "Clone, copy, and change the permissions on the centos template that lxc will use."; - -} - -bundle agent edit_lxc_centos_template -{ - files: - - "/usr/share/lxc/templates/lxc-centos" - create => "false", - edit_line => replace_release_url; - - reports: - "The release url probably needs modification, to change 10 to 11.1 (at the time of writing). This bundle makes the appropriate change, with some help from other bundles (replace_release_url and new_release_url)."; - -} - - -bundle edit_line replace_release_url -{ - replace_patterns: - - "RELEASE_URL=\"$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.10.$arch.rpm\".*" - replace_with => new_release_url; - reports: - "Trying to find the current release url line"; - -} - -body replace_with new_release_url -{ - replace_value => "RELEASE_URL=\"$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.11.1.$arch.rpm\""; - occurrences => "all"; - -} - -bundle agent create_centos_container -{ - - commands: - "/usr/bin/lxc-create -n $(global_vars.container_name) -t centos -- m 5"; - - reports: - "This bundle uses a command to create the container using the centos template that was downloaded earlier"; - -} - - - -bundle agent configure_centos_container -{ - - files: - - "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0" - create => "false", - edit_line => modify_ifcfg; - - "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/sysconfig/network" - create => "false", - edit_line => add_gateway_line; - - "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/resolv.conf" - create => "true", - edit_line => add_nameserver; - - reports: - "The default configuration of the container requires some modification to define a static IP address. This bundle modifies the appropriate files and also adds some information for DNS to resolv.conf."; - -} - -bundle edit_line modify_ifcfg -{ - replace_patterns: - - "BOOTPROTO=dhcp" - replace_with => change_bootproto; - - insert_lines: - "IPADDR=$(global_vars.container_ip)"; - "NETMASK=255.255.255.0"; - -} - -body replace_with change_bootproto -{ - replace_value => "BOOTPROTO=static"; - occurrences => "all"; -} - -bundle edit_line add_gateway_line -{ - - insert_lines: - "GATEWAY=$(global_vars.gateway_ip)"; - -} - -bundle edit_line add_nameserver -{ - - insert_lines: - "nameserver $(global_vars.gateway_ip)"; - -} - -bundle agent start_centos_container -{ - - commands: - "/bin/rm /var/lib/lxc/cfe-centos-2/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0.cf-before-edit"; - "/usr/bin/lxc-start -d -n $(global_vars.container_name)"; - reports: - "This bundle starts the container that was defined earlier, using a command."; - -} - -bundle agent install_nfs -{ - - vars: - - "match_package" slist => { - "nfs-utils" - }; - - packages: - "$(match_package)" - package_policy => "add", - package_method => yum; - -} - -bundle agent configure_nfs -{ - - files: - - "/var/lib/lxc/$(global_vars.container_name)/rootfs/etc/exports" - create => "true", - edit_line => add_export_line; - "/var/cfengine/masterfiles/def.cf" - create => "false", - edit_line => modify_def; - - reports: - "NFS and CFEngine require some modifications to support the network bridge and container."; - -} - -bundle edit_line add_export_line -{ - - insert_lines: - "/home $(global_vars.host_ip)(rw,sync,no_root_squash,no_subtree_check)"; - -} - -bundle edit_line modify_def -{ - replace_patterns: - - "\"$(sys.policy_hub)/16\".*" - replace_with => change_acl; - -} - -body replace_with change_acl -{ - replace_value => "\"$(sys.policy_hub)/16\",\"192.168.122.*\","; - occurrences => "all"; -} - - - - -bundle agent start_nfs -{ - - methods: - - "any" usebundle => change_service_state("rpcbind","restart"); - "any" usebundle => change_service_state("nfs","restart"); - "any" usebundle => change_service_state("nfslock","restart"); - - reports: - "This bundle starts NFS and related services. It uses restart rather than start just in case the services were already running and modifications made earlier need to be recognized."; - -} - -bundle agent setup_ssh_connection_to_container -{ - - commands: - - "/usr/bin/sshpass -p \"password\" /usr/bin/ssh -o StrictHostKeyChecking=no root@$(global_vars.container_ip) /usr/bin/yum -y install openssh-server openssh-clients"; - "/usr/bin/sshpass -p \"password\" /usr/bin/ssh-copy-id -i /root/.ssh/id_rsa.pub root@$(global_vars.container_ip)"; - - reports: - "Setting up an ssh connection to the container will be used to pass commands from the host machine."; - -} - -bundle agent setup_nfs_on_container -{ - - commands: - "/usr/bin/ssh $(global_vars.container_ip) /usr/bin/yum -y install nfs-utils"; - reports: - "NFS needs to be installed onto the container. This bundle does this using a command call to ssh, and in turn to the yum installer on the container."; - -} - -bundle agent mount_shared_folder_on_container -{ - - commands: - "/usr/bin/ssh $(global_vars.container_ip) /bin/mount $(global_vars.container_ip):/root /root/mount"; - reports: - "After NFS is installed on the container, the shared directory between the two machines can be mounted."; - -} - -bundle agent install_cfengine_on_container -{ - - commands: - "/usr/bin/ssh $(global_vars.container_ip) /bin/chmod a+x /root/mount/quick-install-cfengine-cfengine-enterprise.sh"; - "/usr/bin/ssh $(global_vars.container_ip) /root/mount/quick-install-cfengine-cfengine-enterprise.sh agent"; - reports: - "After the shared folder is mounted, a call to the CFEngine script install can be made from the host via ssh to the container"; - -} - -bundle agent bootstrap_cfengine_on_container -{ - - commands: - "/usr/bin/ssh $(global_vars.container_ip) /var/cfengine/bin/cf-agent --bootstrap $(global_vars.gateway_ip)"; - - reports: - "CFEngine should now be installed, and this bundle will boostrap it to the host machine that is running hub."; - "Note: changes may need to be made to /var/cfengine/masterfiles/controls/cf_serverd.cf on the hub to properly use the container as a CFEngine host across a network bridge (in this tutorial via the 192.168.122.1 gateway). Look for the section '!am_policy_hub.enterprise::' and change all three lines that state 'admit => { \"$(sys.policy_hub)\"};' to read 'admit => { \"$(sys.policy_hub)\",\"192.168.122.1\" };'."; - -} - - - diff --git a/examples/tutorials/nfs_and_containers.markdown b/examples/tutorials/nfs_and_containers.markdown deleted file mode 100644 index 5a0b5cda1..000000000 --- a/examples/tutorials/nfs_and_containers.markdown +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: default -title: NFS and LXC -published: false -sorting: 110 -tags: [examples, tutorials, nfs, lxc, containers] ---- - -1. Downloaded nfs_and_containers.cf). Place it in /var/cfengine/masterfiles/nfs_and_containers.cf. -2. Run the following commands as root on the command line: - - ```console - ``` -The policy has some notes in reports for several of the bundles used in the bundle sequence. The information will also be shown as output when running the policy using cf-agent as described above. - - - -## Full Policy ## - -[%CFEngine_include_snippet(documentation/examples/tutorials/nfs_and_containers.cf, .* )%] diff --git a/examples/tutorials/render-files-with-mustache-templates.markdown b/examples/tutorials/render-files-with-mustache-templates.markdown index 6928f1155..b7f692dae 100644 --- a/examples/tutorials/render-files-with-mustache-templates.markdown +++ b/examples/tutorials/render-files-with-mustache-templates.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Render files with Mustache templates +title: Rendering files with Mustache templates sorting: 15 published: true -tags: [Examples, Tutorials, mustache] --- @@ -44,6 +43,8 @@ Allowed users
Create a file called `/tmp/myapp.conf.template` with the following content: ``` +[file=myapp.conf.template] +{% raw %} Port {{port}} Protocol {{protocol}} Filepath {{filepath}} @@ -51,6 +52,7 @@ Encryption {{encryption-level}} Loglevel {{loglevel}} Allowed users {{#users}} {{user}}={{level}}{{/users}} +{% endraw %} ``` 2. Create CFEngine policy @@ -58,6 +60,7 @@ Allowed users {{#users}} Create a file called `/tmp/editconfig.cf` with the following content: ```cf3 +[file=editconfig.cf] bundle agent myapp_confs { files: @@ -93,14 +96,16 @@ In this policy we tell CFEngine to ensure a file called `myapp.conf` exists. The Run CFEngine: -```console -# /var/cfengine/bin/cf-agent /tmp/editconfig.cf +```command +/var/cfengine/bin/cf-agent /tmp/editconfig.cf ``` Verify the result: -```console -# cat /tmp/myapp.conf +```command +cat /tmp/myapp.conf +``` +```output Port 3508 Protocol 2 Filepath /mypath/ diff --git a/examples/tutorials/report_inventory_remediate_sec_vulnerabilities.markdown b/examples/tutorials/report_inventory_remediate_sec_vulnerabilities.markdown index 482cdce78..2dba7db86 100644 --- a/examples/tutorials/report_inventory_remediate_sec_vulnerabilities.markdown +++ b/examples/tutorials/report_inventory_remediate_sec_vulnerabilities.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Reporting and Remediation of Security Vulnerabilities +title: Reporting and remediation of security vulnerabilities sorting: 10 published: true -tags: [Examples, Tutorials, Enterprise, Inventory, Dashboard, Alerts] --- ## Prerequisites ## @@ -39,6 +38,7 @@ This bundle will check if the host is vulnerable to the CVE, define a class interface in CFEngine Enterprise. ```cf3 +[file=inventory_CVE_2014_6271.cf] bundle agent inventory_CVE_2014_6271 { meta: @@ -150,13 +150,14 @@ See the dashboard alert in action. ![See an the dashboard alert in action - alert details 1](report_inventory_remediate_sec_vulnerabilities_2014-09-29-Selection_014.jpg) ![See an the dashboard alert in action - specifc alert details](report_inventory_remediate_sec_vulnerabilities_2014-09-29-Selection_015.jpg) -## Remediate Vulnerabilities ## +## Remediate vulnerabilities ## Now that we know the extent of exposure lets ensure bash gets updated on some of the affected systems. Save the following policy into `services/autorun/remediate_CVE_2014_6271.cf` ```cf3 +[file=remediate_CVE_2014_6271.cf] bundle agent remediate_CVE_2014_6271 { meta: diff --git a/examples/tutorials/reporting.markdown b/examples/tutorials/reporting.markdown index 35fe811b7..ebaa8f6aa 100644 --- a/examples/tutorials/reporting.markdown +++ b/examples/tutorials/reporting.markdown @@ -3,7 +3,6 @@ layout: default title: Reporting published: true sorting: 80 -tags: [overviews, reports, reporting] --- No promises made in CFEngine imply automatic aggregation of data to a central location. In diff --git a/examples/tutorials/reporting/command-line-reports.markdown b/examples/tutorials/reporting/command-line-reports.markdown index 827b36c63..c4cb2af2a 100644 --- a/examples/tutorials/reporting/command-line-reports.markdown +++ b/examples/tutorials/reporting/command-line-reports.markdown @@ -1,6 +1,6 @@ --- layout: default -title: Command-Line Reports +title: Command-Line reports published: true sorting: 60 --- @@ -11,19 +11,19 @@ sorting: 60 The following report topics are included: -[CFEngine output levels][Command-Line Reports#CFEngine output levels] +[CFEngine output levels][Command-Line reports#CFEngine output levels] -[Creating custom reports][Command-Line Reports#Creating custom reports] +[Creating custom reports][Command-Line reports#Creating custom reports] -[Including data in reports][Command-Line Reports#Including data in reports] +[Including data in reports][Command-Line reports#Including data in reports] -[Excluding data from reports][Command-Line Reports#Excluding data from reports] +[Excluding data from reports][Command-Line reports#Excluding data from reports] -[Creating custom logs][Command-Line Reports#Creating custom logs] +[Creating custom logs][Command-Line reports#Creating custom logs] -[Redirecting output to logs][Command-Line Reports#Redirecting output to logs] +[Redirecting output to logs][Command-Line reports#Redirecting output to logs] -[Change detection: tripwires][Command-Line Reports#Change detection: tripwires] +[Change detection: tripwires][Command-Line reports#Change detection: tripwires] ### CFEngine output levels @@ -130,7 +130,8 @@ reports: The outcome of this promise is a file called /tmp/report.html which contains the following output: -```cf3 +```html +[file=report.html] Name of this host is: atlas
Type of this host is: linux
@@ -200,7 +201,7 @@ reports: This produces the following standard output: -```cf3 +``` R: State of otherprocs peaked at Tue Dec 1 12:12:21 2014 R: The peak measured state was q = 98: @@ -253,7 +254,7 @@ number_of_lines => "$(lines)"; This produces the following output: -```cf3 +``` R: /etc/passwd except R: at:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bash R: avahi:x:103:105:User for Avahi:/var/run/avahi-daemon:/bin/false @@ -365,8 +366,10 @@ log_string => "$(sys.date) $(x) promise status"; This generates three different logs with the following output: -```cf3 -atlas$ more /tmp/private_keptlog.log +```command +more /tmp/private_keptlog.log +``` +```output Sun Dec 6 11:58:16 2009 /tmp/xyz promise status Sun Dec 6 11:58:43 2009 /tmp/xyz promise status ``` @@ -443,7 +446,7 @@ depth => "$(d)"; In CFEngine Enterprise, reports of the following form are generated when these promises are kept by the agent: -```cf3 +``` Change detected File change Sat Dec 5 18:27:44 2013 group for /tmp/testfile changed 100 -> 0 Sat Dec 5 18:27:44 2013 /tmp/testfile diff --git a/examples/tutorials/reporting/monitoring-reporting.markdown b/examples/tutorials/reporting/monitoring-reporting.markdown index 05cecca5f..ae4f01c39 100644 --- a/examples/tutorials/reporting/monitoring-reporting.markdown +++ b/examples/tutorials/reporting/monitoring-reporting.markdown @@ -1,11 +1,11 @@ --- layout: default -title: Monitoring and Reporting +title: Monitoring and reporting published: true sorting: 10 --- -## What are Monitoring and Reporting? +## What are monitoring and reporting? Monitoring is the sampling of system variables at regular intervals in order to present an overview of actual changes taking place over time. @@ -21,7 +21,7 @@ discovered changes and faults. The challenge of both these activities is to compare intended or promised, behavior with the actual observed behavior of the system. -## Should Monitoring and Configuration be Separate? +## Should monitoring and configuration be separate? The traditional view of IT operations is that configuration, monitoring, and reporting are three different things that should not be joined. Traditionally, diff --git a/examples/tutorials/tags.markdown b/examples/tutorials/tags.markdown index c00d29b1b..f8301367f 100644 --- a/examples/tutorials/tags.markdown +++ b/examples/tutorials/tags.markdown @@ -3,7 +3,6 @@ layout: default title: Tags for variables, classes, and bundles published: true sorting: 14 -tags: [tags, meta] --- ## Introduction @@ -34,7 +33,7 @@ so it's available out of the box in either Community or Enterprise. In the Enterprise Mission Portal, you can then make a report for "Ports listening" across all your machines. For more details, see -[Enterprise Reporting][Enterprise Reporting] +[Enterprise reporting][Enterprise reporting] Class tags work exactly the same way, you just apply them to a `classes` promise with the `meta` attribute. @@ -102,12 +101,12 @@ This will create class `x` and variable `a` with tag `inventory`. Then it will create class `y` and variable `b` with tags `report` and `attribute_name=My vars`. -## Enterprise Reporting with tags +## Enterprise reporting with tags In CFEngine Enterprise, you can build reports based on tagged variables and classes. -Please see [Enterprise Reporting][Enterprise Reporting] for a full tutorial, +Please see [Enterprise reporting][Enterprise reporting] for a full tutorial, including troubleshooting possible errors. In short, this is an extremely easy way to categorize various data accessible to the agent. diff --git a/examples/tutorials/write-cfengine-policy.markdown b/examples/tutorials/write-cfengine-policy.markdown index 691dc8f4c..703372626 100644 --- a/examples/tutorials/write-cfengine-policy.markdown +++ b/examples/tutorials/write-cfengine-policy.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Write CFEngine policy +title: Writing CFEngine policy published: true sorting: 3 -tags: [getting started, tutorial] --- To define new Desired States in CFEngine, you need to write policy files. These are plain text-files, traditionally with a `.cf` extension. @@ -15,17 +14,20 @@ by default, and it executes policies found locally in the `/var/cfengine/inputs` directory. The default policy entry is a file called `promises.cf`. In this file you normally reference bundles and other policy files. -## Bundles, Promise types, and Classes oh my! +## Bundles, promise types, and classes oh my! These concepts are core to CFEngine so they are covered in brief here. For more -detailed information see the Language Concepts section of the Reference manual. +detailed information see the Language concepts section of the Reference manual. ### Bundles Bundles are re-usable and blocks of CFEngine policy. The following defines a *bundle* called `my_test`, and it is a bundle for the agent. ```cf3 -bundle agent my_test{..policy-code...} +bundle agent my_test +{ + # ... +} ``` A bundle contains one or more promise types. @@ -64,8 +66,8 @@ you very granular control. To see a list of available classes on your host, just type the following command: -```console -# cf-promises --show-classes +```command +cf-promises --show-classes ``` ## Running policy @@ -75,12 +77,15 @@ final policy. As for classes we will use linux to define that the file `/tmp/hello-world` must exists on all hosts of type *linux*: ```cf3 -bundle agent my_test{ - files: - linux:: - "/tmp/hello-world" - create => "true"; +[file=my_test.cf] +bundle agent my_test +{ + files: + linux:: + "/tmp/hello-world" + create => "true"; } + bundle agent __main__ { methods: "my_test"; @@ -92,7 +97,7 @@ Let's save this policy in `/tmp/my-policy.cf`. You can now run this policy either in Distributed (client-server) System or in a Stand Alone system. The next two sections will cover each of the options. -## Option#1: Running the Policy on a Stand alone system +### Option#1: Running the policy on a stand alone system Since CFEngine is fully distributed we can run policies locally. This can come in handy as the result of a run is instant, especially during the design phase @@ -105,29 +110,29 @@ this as it is the same cf-agent that runs on the hosts as on the Policy Server. **Tip:** Whenever you make or modify a policy, you can use the `cf-promises` command to run a syntax check: -```console -# cf-promises -f /tmp/my-policy.cf +```command +cf-promises -f /tmp/my-policy.cf ``` Unless you get any output, the syntax is correct. Now, to run this policy, simply type: -```console -# cf-agent -Kf /tmp/my-policy.cf +```command +cf-agent -Kf /tmp/my-policy.cf ``` As you can see, the response is immediate! Running CFEngine locally like this is ideal for testing out new policies. To check that the file has been successfully created type: -```console -# ls /tmp/hello-world -l +```command +ls /tmp/hello-world -l ``` If you want to see what the agent is doing during its run, you can run the agent in verbose mode. Try: -```console -# cf-agent -Kf /tmp/my-policy.cf --verbose +```command +cf-agent -Kf /tmp/my-policy.cf --verbose ``` In a Stand Alone system, to make and run a policy remember to: @@ -162,6 +167,7 @@ Now we need to tell CFEngine that there is a new policy in town: 1. Create `/var/cfengine/masterfiles/def.json` with the following content: ```json +[file=def.json] { "inputs": [ "my-policy.cf" ] } @@ -170,8 +176,8 @@ Now we need to tell CFEngine that there is a new policy in town: On the policy server you can run the following command to make sure the syntax is correct. -```console -# cf-agent -cf /var/cfengine/masterfiles/promises.cf +```command +cf-promises -cf /var/cfengine/masterfiles/promises.cf ``` After some period of time (CFEngine runs by default every 5 minutes), log in to diff --git a/examples/tutorials/writing-and-serving-policy.markdown b/examples/tutorials/writing-and-serving-policy.markdown index 99beb6fc4..c40ff2073 100644 --- a/examples/tutorials/writing-and-serving-policy.markdown +++ b/examples/tutorials/writing-and-serving-policy.markdown @@ -1,41 +1,29 @@ --- layout: default -title: Writing and Serving Policy +title: Writing and serving policy published: true sorting: 100 --- -* [About Policies and Promises][Writing and Serving Policy#About Policies and Promises] - * [What Are Promises][Writing and Serving Policy#What Are Promises] - * [The Value of a Promise][Writing and Serving Policy#The Value of a Promise] - * [Anatomy of a Promise][Writing and Serving Policy#Anatomy of a Promise] -* [Policy Workflow][Writing and Serving Policy#Policy Workflow] -* [How Promises Work][Writing and Serving Policy#How Promises Work] - * [Summary for Writing, Deploying and Using Promises][Writing and Serving Policy#Summary for Writing, Deploying and Using Promises] -* [Best Practices][Writing and Serving Policy#Best Practices] -* [Layers of Abstraction in Policy][Layers of Abstraction in Policy] -* [Promises Available in CFEngine][Promises Available in CFEngine] -* [Authoring Policy Tools & Workflow][Authoring Policy Tools & Workflow] - -## About Policies and Promises ## +## About policies and promises ## Central to CFEngine's effectiveness in system administration is the concept of a "promise," which defines the intent and expectation of how some part of an overall system should behave. CFEngine emphasizes the promises a client makes to the overall CFEngine network. Combining promises with patterns to describe where and when promises should apply is what CFEngine is all about. -This document describes in brief what a promise is and what a promise does. There are other resources for finding out additional details about "promises" in the See Also section at the end of this document. +This document describes in brief what a promise is and what a promise does. There are other resources for finding out additional details about "promises" in the See also section at the end of this document. -### What Are Promises ### +### What are promises ### A promise is the documentation or definition of an intention to act or behave in some manner. They are the rules which CFEngine clients are responsible for implementing. -### The Value of a Promise ### +### The value of a promise ### When you make a promise it is an effort to improve trust, which is an economic time-saver. If you have trust then there is less need to verify, which in turn saves time and money. When individual components are empowered with clear guidance, independent decision making power, and the trust that they will fulfil their duties, then systems that are complex and scalable, yet still manageable, become possible. -### Anatomy of a Promise ### +### Anatomy of a promise ### ```cf3 bundle agent hello_world @@ -50,26 +38,25 @@ bundle agent hello_world } ``` -## How Promises Work ## +## How promises work ## Everything in CFEngine can be thought of as a promise to be kept by different resources in the system. In a system that delivers a web site using Apache, an important promise may be to make sure that the `httpd` or `apache` package is installed, running, and accessible on port 80. -### Summary for Writing, Deploying and Using Promises ### +### Summary for writing, deploying and using promises ### Writing, deploying, and using CFEngine `promises` will generally follow these simple steps: 1. Using a text editor, create a new file (e.g. `hello_world.cf`). -2. Create a bundle and promise in the file (see ["Hello World" Policy Example][Examples and Tutorials#"Hello World" Policy Example]). +2. Create a bundle and promise in the file (see ["Hello world" policy example][Examples and tutorials#"Hello world" policy example]). 3. Save the file on the policy server somewhere under `/var/cfengine/masterfiles` (can be under a sub-directory). 4. Let CFEngine know about the `promise` on the `policy server`, generally in the file `/var/cfengine/masterfiles/promises.cf`, or a file elsewhere but referred to in `promises.cf`. - * Optional: it is also possible to call a bundle manually, using `cf-agent`. 5. Verify the `policy file` was deployed and successfully run. -See [Tutorial for Running Examples][Examples and Tutorials#Tutorial for Running Examples] for a more detailed step by step tutorial. +See [Tutorial for running examples][Examples and tutorials#Tutorial for running examples] for a more detailed step by step tutorial. -## Policy Workflow ## +## Policy workflow ## CFEngine does not make absolute choices for you, like other tools. Almost everything about its behavior is a matter of policy and can be changed. @@ -110,14 +97,14 @@ recover from deployment errors easily. By placing the burden of responsibility for decision at the top, and for implementation at the bottom, we avoid needless fragility and keep two independent quality assurance processes apart. -## Best Practices ## +## Best practices ## -* [Policy Style Guide][Policy Style Guide] This covers punctuation, whitespace, and other styles to remember when writing policy. +* [Policy style guide][Policy style guide] This covers punctuation, whitespace, and other styles to remember when writing policy. -* [Bundles Best Practices][Bundles Best Practices] Refer to this page as you decide when to make a bundle and when to use classes and/or variables in them. +* [Bundles best practices][Bundles best practices] Refer to this page as you decide when to make a bundle and when to use classes and/or variables in them. -* [Testing Policies][Testing Policies] This page describes how to locally test CFEngine and play with configuration files. +* [Testing policies][Testing policies] This page describes how to locally test CFEngine and play with configuration files. -## See Also ## +## See also ## * [Promises][Promises] diff --git a/examples/tutorials/writing-and-serving-policy/authoring-policy-tools-and-workflow.markdown b/examples/tutorials/writing-and-serving-policy/authoring-policy-tools-and-workflow.markdown index c4d4cf264..9e23a9278 100644 --- a/examples/tutorials/writing-and-serving-policy/authoring-policy-tools-and-workflow.markdown +++ b/examples/tutorials/writing-and-serving-policy/authoring-policy-tools-and-workflow.markdown @@ -1,6 +1,6 @@ --- layout: default -title: Authoring Policy Tools & Workflow +title: Authoring policy tools & workflow published: true sorting: 5 --- @@ -47,15 +47,17 @@ Method Two: Create Masterfiles Repository Using the GitHub Application 5. Click on the "Create" button at the bottom of the screen. A new repository will be created in your local GitHub folder. -#### Initialize Git Repository in Masterfiles on the Hub #### +#### Initialize Git Repository in Masterfiles on the Hub -1. `> cd /var/cfengine/masterfiles` -2. `> echo cf_promises_validated >> .gitignore` -3. `> echo cf_promises_release_id >> .gitignore` -4. `> git init` -5. `> git commit -m "First commit"` -6. `> git remote add origin https://github.com/GitUserName/cfengine-masterfiles.git` -7. `> git push -u origin master` +```bash +cd /var/cfengine/masterfiles +echo cf_promises_validated >> .gitignore +echo cf_promises_release_id >> .gitignore +git init +git commit -m "First commit" +git remote add origin https://github.com/GitUserName/cfengine-masterfiles.git +git push -u origin master +``` **Note:** `cf_promises_validated` and `cf_promises_release_id` should be explicitly excluded from VCS as shown above. They are generated files and involved in controlling policy updates. If these files are checked into the repository it can create issues with policy distribution. @@ -85,10 +87,21 @@ B) Or, change the remote url to `https://GitUserName@password:github.com/GitUser #### Create a Remote in Masterfiles on the Hub to Masterfiles on GitHub #### 1. Change back to the `masterfiles` directory, if not already there: - * `> cd /var/cfengine/masterfiles` + +```command +cd /var/cfengine/masterfiles +``` 2. Create the remote using the following pattern: - * `> git remote add upstream ssh://git@github.com/GitUserName/cfengine-masterfiles.git`. -3. Verify the remote was registered properly by typing `git remote -v` and pressing enter. + +```command +git remote add upstream ssh://git@github.com/GitUserName/cfengine-masterfiles.git +``` + +3. Verify the remote was registered properly: + +```command +git remote -v +``` * You will see the remote definition in a list alongside any other previously defined remote entries. #### Add a Promise that Pulls Changes to Masterfiles on the Hub from Masterfiles on GitHub #### @@ -97,6 +110,7 @@ B) Or, change the remote url to `https://GitUserName@password:github.com/GitUser 2. Add the following text to the `vcs_update.cf` file: ```cf3 +[file=vcs_update.cf] bundle agent vcs_update { commands: @@ -115,6 +129,7 @@ body contain masterfiles_contain 4. Add bundle and file information to `/var/cfengine/masterfiles/promises.cf`. Example (where `...` represents existing text in the file, omitted for clarity): ```cf3 +[file=promises.cf] body common control { diff --git a/examples/tutorials/writing-and-serving-policy/bundles-best-practices.markdown b/examples/tutorials/writing-and-serving-policy/bundles-best-practices.markdown index c86fa34c7..b53f371cb 100644 --- a/examples/tutorials/writing-and-serving-policy/bundles-best-practices.markdown +++ b/examples/tutorials/writing-and-serving-policy/bundles-best-practices.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Bundles Best Practices +title: Bundles best practices published: true sorting: 20 -tags: [manuals, bundles, policy, best practices] --- The following contains practices to remember when creating bundles as @@ -62,6 +61,7 @@ Write the promises (which may or may not be ordered) using a parameter for the d names, and then call the method passing the list of names as a parameter to reduce the amount of code. ```cf3 +[file=testbundle.cf] bundle agent testbundle { vars: diff --git a/examples/tutorials/writing-and-serving-policy/controlling-frequency.markdown b/examples/tutorials/writing-and-serving-policy/controlling-frequency.markdown index 6fd12fbd0..123a05c87 100644 --- a/examples/tutorials/writing-and-serving-policy/controlling-frequency.markdown +++ b/examples/tutorials/writing-and-serving-policy/controlling-frequency.markdown @@ -1,14 +1,59 @@ --- layout: default -title: Controlling Frequency +title: Controlling frequency published: true sorting: 90 -tags: [manuals, systems, configuration management, automation, control, frequency, performance] --- -When checking a series of expensive functions and verifying complex promises, -you may want to make sure that CFEngine is not checking too frequently. One -way of doing this is classes and class expression, another is using locks. +By default CFEngine runs relatively frequently (every 5 minutes) but you may not +want every promise to be evaluated each agent execution. Classes and promise +locks are the two primary ways in which a promises frequency can be controlled. +Classes are the canonical way of controlling if a promise is in context and +should be evaluated. Promise locks control frequency based on the number of +minutes since the last promise actuation. + +## Controlling frequency using classes + +Classes are the canonical way of controlling promise executions in CFEngine. + +Use time based classes to restrict promises to run during a specific period of time. For example, here `sshd` promises to be the latest version available, but only on Tuesdays during the first 15 minutes of the 5:00 hour. + +```cf3 +bundle agent __main__ +{ + packages: + Tuesday.Hr05_Q1:: + "sshd" + version => "latest", + comment => "Make sure sshd is at the latest version, but only Tuesday between 5:00 and 5:15am"; +} +``` + +Persistent classes can exist for a period of time, across multiple executions of +`cf-agent`. Persistent classes can be used to avoid re-execution of a promise. +For example, here `/tmp/heartbeat.dat` promises to update it's timestamp when +`heartbeat_repaired` is not defined. When the file is repaired the class +`heartbeat_repaired` is defined for 10 minutes causing the promise to be out of +context during subsequent executions for the next 10 minutes. + +```cf3 +bundle agent __main__ +{ + files: + !heartbeat_repaired:: + "/tmp/heartbeat.dat" + create => "true", + touch => "true", + classes => persistent_results( "heartbeat", 10 ); +} +body classes persistent_results( prefix, time ) +{ + inherit_from => results( "namespace", "$(prefix)" ); + persist_time => "$(time)"; +} +``` + +## Controlling frequency using promise locks CFEngine incorporates a series of locks which prevent it from checking promises too often, and which prevent it from spending too long trying to @@ -17,19 +62,17 @@ a way that you can start several CFEngine components simultaneously without them interfering with each other. You can control two things about each kind of action in CFEngine: - ifelapsed - -The minimum time (in minutes) which should have passed since the last time -that promise was verified. It will not be executed again until this amount of -time has elapsed. Default time is 1 minute. +* `ifelapsed` - The minimum time (in minutes) which should have passed since the + last time that promise was verified. It will not be executed again until this + amount of time has elapsed. If the value is `0` the promise has no lock and + will always be executed when in context. Additionally, a value of `0` disables + function caching. Default time is `1` minute. - expireafter - -The maximum amount (in minutes) of time `cf-agent` should wait for an old -instantiation to finish before killing it and starting again. You can think -about [`expireafter`][cf-agent#expireafter] as a timeout to use when a promise verification may -involve an operation that could wait indefinitely. Default time is 120 -minutes. +* `expireafter` - The maximum amount (in minutes) of time `cf-agent` should wait + for an old instantiation to finish before killing it and starting again. You + can think about [`expireafter`][cf-agent#expireafter] as a timeout to use when + a promise verification may involve an operation that could wait indefinitely. + Default time is `120` minutes. You can set these values either globally (for all actions) or for each action separately. If you set global and local values, the local values override the @@ -46,7 +89,7 @@ body agent control This setting tells CFEngine not to verify promises until 60 minutes have elapsed, ie ensures that the global frequency for all promise verification is one hour. This global setting of one hour could be changed for a specific -promise body by setting [`ifelapsed`][Promise Types#ifelapsed] in the promise body. +promise body by setting [`ifelapsed`][Promise types#ifelapsed] in the promise body. ```cf3 body action example @@ -63,3 +106,29 @@ atomic promise checks on the same objects (packages, users, files, etc.). Several different `cf-agent` instances can run concurrently. The locks ensure that promises will not be verified by two cf-agents at the same time or too soon after a verification. + +For example, here the `sshd` package promises to be at the latest version. It +has the `if_elapsed_day` action body attached which sets `ifelapsed` to `1440` +causing the promise lock to persist for a day effectively restricting the +promise to run just once a day. + +```cf3 +bundle agent __main__ +{ + packages: + "sshd" + version => "latest", + action => if_elapsed_day, + comment => "Make sure sshd is at the latest version, but just once a day."; +} +``` + +**Note:** + +* Promise locks are ignored when CFEngine is run with the `--no-lock` or `-K` + option, e.g. a common **manual** execution of the agent, `cf-agent -KI` would + not respect promises that are locked from a recent execution. +* Locks are purged based on database utilization and age in order to maintain + the integrity and health of the underlying lock database. + +**See also:** [cf_lock.lmdb][CFEngine directory structure#state/cf_lock.lmdb] diff --git a/examples/tutorials/writing-and-serving-policy/editors.markdown b/examples/tutorials/writing-and-serving-policy/editors.markdown index c4f477a7a..97f1187a6 100644 --- a/examples/tutorials/writing-and-serving-policy/editors.markdown +++ b/examples/tutorials/writing-and-serving-policy/editors.markdown @@ -3,7 +3,6 @@ layout: default title: Editors published: true sorting: 10 -tags: [tools, editor, vim, emacs, vscode, kate, sublime text, atom, eclipse ] --- Using an editor that provides syntax highlighting and other features can significantly enhance prodcutivity and quality of life. @@ -30,7 +29,7 @@ Vi/Vim users can edit CFEngine policies with Neil Watson's CFEngine 3 scripts, a Microsoft VS Code users have syntax highlighting thanks to AZaugg. Install the syntax highlighting and snippets directly from within Visual Studio Code by running ext install vscode-cfengine. -![Visual Studio Code](guide-writing-and-serving-policy-editors-visual-studio-code.png) +[![Visual Studio Code](guide-writing-and-serving-policy-editors-visual-studio-code.png)](https://marketplace.visualstudio.com/items?itemName=azaugg.vscode-cfengine) ## Sublime Text @@ -39,11 +38,19 @@ Sublime Text 2 and 3 users have syntax highlighting and snippets thanks to Valer ![Sublime Text](guide-writing-and-serving-policy-editors-sublime-text.jpg) -## Atom +## Zed -Using Githubs hackable editor? You can get syntax highlighting with the language-cfengine3 package. +Syntax highlighting is available in the [Zed](https://zed.dev/) editor, via [the **CFEngine** extension](https://zed.dev/extensions?q=CFEngine). -![Atom](guide-writing-and-serving-policy-editors-atom.png) +[![Zed](guide-writing-and-serving-policy-editors-zed.png)](https://zed.dev/extensions?q=CFEngine) + +## Atom / Pulsar + +Using Githubs hackable editor? +You can get syntax highlighting with the [language-cfengine3](https://github.com/olehermanse/language-cfengine3) package. +This extension is available in both [Atom (discontinued)](https://github.blog/news-insights/product-news/sunsetting-atom/) and [Pulsar](https://pulsar-edit.dev/), a fork of Atom. + +[![Atom](guide-writing-and-serving-policy-editors-atom.png)](https://web.pulsar-edit.dev/packages/language-cfengine3) ## Eclipse diff --git a/examples/tutorials/writing-and-serving-policy/external_data.markdown b/examples/tutorials/writing-and-serving-policy/external_data.markdown index 5e7475b58..bdec2c370 100644 --- a/examples/tutorials/writing-and-serving-policy/external_data.markdown +++ b/examples/tutorials/writing-and-serving-policy/external_data.markdown @@ -1,9 +1,8 @@ --- layout: default -title: External Data +title: External data published: true sorting: 50 -tags: [manuals, writing policy, external data, augments] --- It is common to integrate CFEngine with external data sources. External data diff --git a/examples/tutorials/writing-and-serving-policy/guide-writing-and-serving-policy-editors-zed.png b/examples/tutorials/writing-and-serving-policy/guide-writing-and-serving-policy-editors-zed.png new file mode 100644 index 000000000..60d69c728 Binary files /dev/null and b/examples/tutorials/writing-and-serving-policy/guide-writing-and-serving-policy-editors-zed.png differ diff --git a/examples/tutorials/writing-and-serving-policy/policy-layers-abstraction.markdown b/examples/tutorials/writing-and-serving-policy/policy-layers-abstraction.markdown index 8cc379c1d..277ea8cfb 100644 --- a/examples/tutorials/writing-and-serving-policy/policy-layers-abstraction.markdown +++ b/examples/tutorials/writing-and-serving-policy/policy-layers-abstraction.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Layers of Abstraction in Policy +title: Layers of abstraction in policy published: true sorting: 2 -tags: [overviews, writing policy, policy] --- CFEngine offers a number of layers of abstraction. The most fundamental atom diff --git a/examples/tutorials/writing-and-serving-policy/policy-style.markdown b/examples/tutorials/writing-and-serving-policy/policy-style.markdown index 07a07bbc5..37f9f76ba 100644 --- a/examples/tutorials/writing-and-serving-policy/policy-style.markdown +++ b/examples/tutorials/writing-and-serving-policy/policy-style.markdown @@ -1,16 +1,15 @@ --- layout: default -title: Policy Style Guide +title: Policy style guide published: true sorting: 10 -tags: [manuals, style, policy] --- Style is a very personal choice and the contents of this guide should only be considered suggestions. We invite you to contribute to the growth of this guide. -## Style Summary +## Style summary * one indent = 2 spaces * avoid letting line length surpass 80 characters. @@ -20,10 +19,10 @@ guide. * promiser = 3 indents, to allow for adding class guards without changing indent * promise attributes = (we suggest 3 or 4 indents) -## Promise Ordering +## Promise ordering There are two common styles that are used when writing policy. The -[Normal Order][Normal Ordering] style dictates that promises should be +[Normal Order][Normal ordering] style dictates that promises should be written in in the Normal Order that the agent evaluates promises in. The other is reader optimized where promises are written in the order they make sense to the reader. Both styles have their merits, @@ -35,7 +34,7 @@ Here is an example of a policy written in the Normal Order. Note how `packages` are listed after `files`. This could confuse a novice who thinks that it is necessary for the files promise to only be attempted after the package promise is kept. However this style can be useful to -a policy expert who is familiar with Normal Ordering. +a policy expert who is familiar with Normal ordering. ```cf3 bundle agent main @@ -76,7 +75,7 @@ Here is an example of a policy written to be optimized for the reader. Note how packages are listed before files in the order which users think about taking imperitive action. This style can make it significantly easier for a novice to understand the desired state, but -it is important to remember that Normal Ordering still applies and +it is important to remember that Normal ordering still applies and that the promises will not be actuated in the order they are written. ```cf3 @@ -113,7 +112,7 @@ bundle agent main } ``` -## Whitespace and Line Length +## Whitespace and line length Spaces are preferred to tab characters. Lines should not have trailing whitespace. Generally line length should not surpass 80 characters. @@ -187,7 +186,7 @@ bundle agent example } ``` -## Policy Comments +## Policy comments In-line policy comments are useful for debugging and explaining why something is done a specific way. We encourage you to document your policy thoroughly. @@ -222,7 +221,7 @@ bundle agent example(param1) } ``` -## Policy Reports +## Policy reports It is common and useful to include reports in policy to get detailed information about what is going on. During a normal agent run the goal is to @@ -259,7 +258,7 @@ polluting the `inform_mode` and `verbose_mode` output, and it allows you to get debug output for ALL policy or just a select bundle which is incredibly useful when debugging a large policy set. -## Promise Handles +## Promise handles Promise handles uniquely identify a promise within a policy. We suggest a simple naming scheme of `bundle_name_promise_type_class_restriction_promiser` to keep handles unique and @@ -329,7 +328,7 @@ bundle agent example Which one do you prefer? -## Naming Conventions +## Naming conventions Naming conventions can also help to provide clarity. @@ -440,7 +439,7 @@ bundle agent main } ``` -## Deprecating Bundles +## Deprecating bundles As your policy library changes over time you may want to deprecate various bundles in favor of newer implimentations. To indicate that a bundle is deprecated we recommend the following style. @@ -490,7 +489,7 @@ bundle agent satellite_bootstrap_main Output the parsed policy in ```cf``` format: -```console +```command cf-promises -f /tmp/example.cf --policy-output-format cf ``` diff --git a/examples/tutorials/writing-and-serving-policy/promises-available-in-cfengine.markdown b/examples/tutorials/writing-and-serving-policy/promises-available-in-cfengine.markdown index 26d763d6d..a08e16d7d 100644 --- a/examples/tutorials/writing-and-serving-policy/promises-available-in-cfengine.markdown +++ b/examples/tutorials/writing-and-serving-policy/promises-available-in-cfengine.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Promises Available in CFEngine +title: Promises available in CFEngine sorting: 4 published: true -tags: [overviews, promises] --- ### meta - information about promise bundles ### diff --git a/examples/tutorials/writing-and-serving-policy/testing-policies.markdown b/examples/tutorials/writing-and-serving-policy/testing-policies.markdown index 9f4646a93..705d68537 100644 --- a/examples/tutorials/writing-and-serving-policy/testing-policies.markdown +++ b/examples/tutorials/writing-and-serving-policy/testing-policies.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Testing Policies +title: Testing policies published: true sorting: 50 -tags: [manuals, systems, configuration management, automation, testing, work directory] --- One of the practical advantages of CFEngine is that you can test it without @@ -23,19 +22,21 @@ To test CFEngine as an ordinary user, do the following: Copy the binaries into the work directory: -``` -host$ mkdir -p ~/.cfagent/inputs -host$ mkdir -p ~/.cfagent/bin -host$ cp /var/cfengine/bin/cf-* ~/.cfagent/bin -host$ cp /var/cfengine/inputs/*.cf ~/.cfagent/inputs +```console +mkdir -p ~/.cfagent/inputs +mkdir -p ~/.cfagent/bin +cp /var/cfengine/bin/cf-* ~/.cfagent/bin +cp /var/cfengine/inputs/*.cf ~/.cfagent/inputs ``` You can test the software and play with configuration files by editing the basic directly in the `~/.cfagent/inputs` directory. For example, try the following: +```console +~/.cfagent/bin/cf-promises +~/.cfagent/bin/cf-promises --verbose +``` - host$ ~/.cfagent/bin/cf-promises - host$ ~/.cfagent/bin/cf-promises --verbose This is always the way to start checking a configuration in CFEngine 3. If a configuration does not pass this check/test, you will not be allowed to use diff --git a/generator/.gitignore b/generator/.gitignore index 1c41f96d3..f58df0670 100644 --- a/generator/.gitignore +++ b/generator/.gitignore @@ -6,4 +6,4 @@ _generated/* /pages/* *.pyc .DS_Store - +node_modules diff --git a/generator/_assets/js/custom.js b/generator/_assets/js/custom.js index 96e4beeba..e6a8d215b 100755 --- a/generator/_assets/js/custom.js +++ b/generator/_assets/js/custom.js @@ -1,4 +1,6 @@ 'use strict'; +import '../styles/cfengine.less'; + var is_mobile = true; $(document).ready(function() { if ($(window).width() > 800) @@ -44,10 +46,20 @@ $(document).ready(function() { ""; var newLine, el, title, link, elClass, url, ToC=''; + var usedIds = {}; $(".article h2, .article h3, .article h4").each(function() { el = $(this); - title = el.text(); - link = "#" + el.attr("id"); + title = el.text() + var id = el.attr("id"); + var uniqueId = id; + if (usedIds[id]){ + uniqueId = id +'-' + usedIds[id]; + el.attr("id",uniqueId); + usedIds[id] += 1; + } else { + usedIds[id] = 1; + } + link = "#" + uniqueId; elClass = "link_" + el.prop("tagName").toLowerCase() url = window.location.pathname; @@ -145,7 +157,8 @@ if (tableOfContents) { var menu = document.querySelector('.top_menu ul'); var overlay = document.querySelector('#overlay'); var openedClass = "opened"; -var openMenuHandler = function (collapseMenu) { + +window.openMenuHandler = function (collapseMenu) { if (collapseMenu.className.indexOf(openedClass) == -1) { collapseMenu.classList.add(openedClass); menu.classList.add('d-b'); @@ -157,7 +170,7 @@ var openMenuHandler = function (collapseMenu) { } } -var openNavigationHandler = function () { +window.openNavigationHandler = function () { document.querySelector('.left-menu').classList.add(openedClass); overlay.style.display = "block"; } @@ -183,6 +196,11 @@ document.querySelector('.top_menu-versions-title > span > span').innerText = doc var mainMenuCopy = document.querySelector('.left-menu ul.mainMenu').cloneNode(true); var clickedMenuHistory = [{href: './', name: 'Home'}]; + +var urlPaths = document.location.pathname.split('/'); +var url = urlPaths[urlPaths.length - 1]; // get last url part +var currentMenuItem = document.querySelector('.left-menu li[data-url="'+ url +'"]'); + var renderNestedMenu = function (href) { if (href == null) { document.querySelector('.left-menu ul.mainMenu').replaceWith(mainMenuCopy); @@ -190,6 +208,10 @@ var renderNestedMenu = function (href) { var ul = mainMenuCopy.querySelector('li[data-url="'+ href +'"]').querySelector('ul').cloneNode(true); ul.classList.add('mainMenu'); document.querySelector('.left-menu ul.mainMenu').replaceWith(ul); + var selected = document.querySelector('li[data-url="'+ url +'"]'); + if (selected){ + selected.className += ' opened current'; + } } applyOnclickToMenuItems(); @@ -231,11 +253,12 @@ var buildBreadcrumbs = function (items) { }) leftMenuBreadcrumbs.innerHTML = html; var lastItem = items[items.length - 1]; - selectedMenu.innerHTML = lastItem.name !== 'Home' ? - ''+ lastItem.name +' ' : - ''; + if (window.innerWidth < 1024){ + selectedMenu.innerHTML = lastItem.name !== 'Home' ? + ''+ lastItem.name +' ' : + ''; + } } -buildBreadcrumbs(clickedMenuHistory); document.querySelector('.menu-back').onclick = function () { if (clickedMenuHistory.length != 1) { @@ -246,29 +269,51 @@ document.querySelector('.menu-back').onclick = function () { } } -var urlPaths = document.location.pathname.split('/'); -var url = urlPaths[urlPaths.length - 1]; // get last url part -var currentMenuItem = document.querySelector('.left-menu li[data-url="'+ url +'"]'); + + if (currentMenuItem != null) { currentMenuItem.className += ' opened current'; + var menuHistory = []; + var currentLink = currentMenuItem.querySelector('a'); + // if selected menu item is a parent we show children on mobile menu + if (currentLink && currentMenuItem.classList.contains('parent')){ + menuHistory.unshift({href: currentLink.getAttribute('href'), name: currentLink.innerText}); + } + var closest = currentMenuItem.closest('ul').closest('li'); - if (window.innerWidth > 1023) { // if the window width more than 1023 then treat the menu as desktop one - var closest = currentMenuItem.closest('ul').closest('li'); - while (true) { - if (!closest) break; + while (true) { + if (!closest) break; + if (window.innerWidth > 1023) { // if the window width more than 1023 then treat the menu as desktop one closest.classList.add('opened'); - closest = closest.closest('ul').closest('li'); + } else { + // Restore history from html + var link = closest.querySelector('a'); + if (link){ + menuHistory.unshift({href: link.getAttribute('href'), name: link.innerText}); + } } + closest = closest.closest('ul').closest('li'); } + clickedMenuHistory = clickedMenuHistory.concat(menuHistory); } +buildBreadcrumbs(clickedMenuHistory); if (window.innerWidth > 1023) { document.querySelectorAll('.mainMenu li.parent > i').forEach(function (element) { element.onclick = function (event) { event.stopImmediatePropagation(); - element.closest('li.parent').classList.toggle('opened'); + var parent = element.closest('li.parent'); + parent.classList.toggle('opened'); + var openedSubmenus = parent.querySelectorAll('.' +openedClass); + openedSubmenus.forEach((subMenu)=>{ + subMenu.classList.remove(openedClass); + }) } }); +} else { + // Small screen + var lastHistoryElement = clickedMenuHistory[clickedMenuHistory.length - 1]; + renderNestedMenu(lastHistoryElement.href); } function fillVersionWrapperSelect(url) { @@ -306,12 +351,17 @@ function selectVersion(value) { window.location = value; } }; +window.selectVersion = selectVersion; -document.addEventListener("DOMContentLoaded", function () { +$(document).ready(function () { fillVersionWrapperSelect('/docs/branches.json') - document.querySelectorAll(".article h1, .article h2, .article h3, .article h4, .article h5, .article h6").forEach(function(el){ - var url = new URL(window.location.href); + const anchors = document.querySelectorAll( + ".article h1[id], .article h2[id], .article h3[id], .article h4[id]" + ); + + anchors.forEach(function(el){ + const url = new URL(window.location.href); el.insertAdjacentHTML('beforeend', ''); }); @@ -320,7 +370,98 @@ document.addEventListener("DOMContentLoaded", function () { e.preventDefault(); navigator.clipboard.writeText(a.href); a.classList.add('url-copied'); + history.replaceState(null, null, a.href); setTimeout(function () { a.classList.remove('url-copied') }, 2000); } - }) + }); + + /** + * Highlight the current TOC item when a user scrolls to the corresponding page section. + */ + (() => { + const tocLinks = document.querySelectorAll('#TOCbox_list li a'); + + if (!tocLinks || !anchors) { + return; + } + + // offsetTop returns offset to the offsetParent, which is main wrapper, we need to add 130px to get actual offset + const fetchOffsets = anchors => [...anchors].map(a => a.offsetTop + 130); + let anchorsOffsets; + let timeout = undefined; + const updateActiveTocItem = () => { + if (timeout) { + clearTimeout(timeout) + } + anchorsOffsets = fetchOffsets(anchors); + + // The current TOC menu item will be calculated in 100 ms after the user stops scrolling. + // Otherwise, there might be redundant calculations. + timeout = setTimeout( () => { + let scrollTop = window.scrollY; + tocLinks.forEach(link => link.classList.remove('current')); + + for (let i = anchorsOffsets.length - 1; i >= 0; i--) { + if (scrollTop > anchorsOffsets[i]) { + setActiveLink(anchors[i].id, i); + break; + } + } + }, 50); // 0.05s threshold + + } + + const setActiveLink = (id, n) => { + const activeLink = document.querySelector(`#TOCbox_list li a[href$="#${id}"]`); + if (activeLink) { + activeLink.classList.add('current'); + } + const tocWrapper = document.getElementById('TOCbox_wrapper'); + const TOC_TOP_OFFSET = 42; + let i = 0; + const offsetArr = [...tocLinks].map((el,)=>{ + const li = el.parentElement; + i+=li.clientHeight + parseInt(window.getComputedStyle(li).getPropertyValue('margin-bottom')); + return i; + }) + const selectedOffset = window.innerHeight-TOC_TOP_OFFSET - (offsetArr[Math.min(offsetArr.length -1 , n + 1)]); + tocWrapper.style.top = (selectedOffset < 0 ? 12 + selectedOffset : 12) + 'px'; + + } + if (window.location.hash){ + const id = window.location.hash.slice(1); + const n = [...anchors].findIndex(a => a.id === id); + setActiveLink(id, n); + } + + + window.addEventListener('scroll', updateActiveTocItem); + window.addEventListener("resize", () => { + // anchors position change when the window is resized + anchorsOffsets = fetchOffsets(anchors); + }); + })(); + + /** + * Display scroll to top button when the scroll reaches 350px + * from the top and window width less than 1280px + */ + (() => { + const scrollToTopBtn = document.getElementById('scrollToTopBtn'); + const showClass = 'show'; + + if (!scrollToTopBtn) { + return; + } + + const handleScrollToTopVisibility = () => { + if (window.scrollY > 350 && window.innerWidth <= 1280) { + scrollToTopBtn.classList.add(showClass); + } else { + scrollToTopBtn.classList.remove(showClass); + } + } + + window.addEventListener('scroll', handleScrollToTopVisibility); + })(); }); diff --git a/generator/_assets/js/dropdown.js b/generator/_assets/js/dropdown.js index f3f21aa31..ac906c823 100644 --- a/generator/_assets/js/dropdown.js +++ b/generator/_assets/js/dropdown.js @@ -13,8 +13,11 @@ document.querySelectorAll('.dropdown-select span').forEach(function (item) { }); document.querySelectorAll('.dropdown-select').forEach(function (item) { + var selected_version = item.querySelector('a[selected="selected"]'); // select first version in dropdown if no selected version // this happens on build previews, because branch name isn't master there - var selected = item.querySelector('a[selected="selected"], a').textContent; - item.querySelector('span div').textContent = selected; + if (!selected_version) { + selected_version = item.querySelector('a'); + } + item.querySelector('span div').textContent = selected_version.textContent; }); diff --git a/generator/_assets/styles/less/article.less b/generator/_assets/styles/less/article.less index 05c214167..a6da8298a 100755 --- a/generator/_assets/styles/less/article.less +++ b/generator/_assets/styles/less/article.less @@ -1,5 +1,5 @@ article { - font-family: "Red Hat Text"; + font-family: "Red Hat Text", Arial, sans-serif; div.article { font-weight: 400; font-size: 16px; @@ -62,35 +62,38 @@ article { h1 { font-size: 36px; line-height: 44px; - margin-bottom: 1.6rem; + margin: 2rem 0; } h2 { font-size: 24px; line-height: 32px; margin-top: 4rem; + margin-bottom: 2rem; } h3 { font-size: 19px; line-height: 24px; - margin-top: 2.4rem; + margin-top: 4rem; + margin-bottom: 2rem; } h4 { - font-size: 18px; + font-size: 16px; line-height: 24px; - margin-top: 2.4rem; + margin-top: 4rem; + margin-bottom: 2rem; } h5 { - font-size: 17px; + font-size: 15px; line-height: 24px; margin-top: 2.4rem; } p { - margin-bottom: 16px; + margin-bottom: 1.2rem; } ul, ol { @@ -111,9 +114,15 @@ article { .article_title { display: flex; align-items: center; + word-wrap: break-word; + grid-gap: 12px; h1 { flex-grow: 1; + max-width: calc(100% - 110px); + @media @phone-down { + max-width: 100%; + } } @media @phone-down { diff --git a/generator/_assets/styles/less/base.less b/generator/_assets/styles/less/base.less index 691098dbe..f39c435a4 100755 --- a/generator/_assets/styles/less/base.less +++ b/generator/_assets/styles/less/base.less @@ -7,7 +7,7 @@ } html { - font-family: "Red Hat Display"; + font-family: "Red Hat Display", Arial, sans-serif; font-size: 62.5%; // 1 rem = 10 px max-width: 100%; overflow-x: hidden; @@ -206,27 +206,87 @@ table { } code { - font-family: "Red Hat Mono"; + font-family: "Red Hat Mono", "Courier New", monospace; background: @gray-100; border-radius: 4px; padding: 0 5px; line-height: 24px; font-size: 15px; + word-wrap: break-word; } div.highlight { background: #F7F7F7; - padding-right: 40px; position: relative; border: 1px solid @gray-300; + border-radius: .4rem; margin: 1.2rem 0 4rem 0; + &.code{ + margin-bottom: 1.6rem; + } + .code_block { + > div { + background: white; + border-radius: .4rem .4rem 0 0; + display: flex; + padding: 1rem 1.6rem; + font-weight: 500; + font-size: 1.6rem; + line-height: 1.6rem; + + .file, .command, .code { + margin-right: 1.2rem; + + &:after { + font-family: bootstrap-icons; + font-style: normal; + } + } + + i.file:after { + content: '\F38B'; + } + + i.command:after { + content: '\F5C3'; + } + + i.code:after { + content: '\F2C8'; + } + } + + pre { + padding: 1.2rem 1.6rem; + border-radius: 0 0 .4rem .4rem; + border-top: 1px solid @gray-300; + font-weight: 500; + font-size: 14px; + } + &.command { + pre { + position: relative; + padding-left: 2.8rem; + &:before { + position: absolute; + top: 1.4rem; + left: 1.2rem; + content: '$'; + font-weight: 500; + font-size: 14px; + } + } + } + } .copy-to-clipboard { position: absolute; - right: 20px; - top: 20px; + right: 0; + top: 5.4rem; cursor: pointer; - background: #F7F7F7; + background: linear-gradient(90deg, rgba(247,247,247,0.5) 0%, rgba(247,247,247,0.9) 20%, rgba(247,247,247,1) 30%, rgba(247,247,247,1) 100%); + width: 4rem; + text-align: center; &:hover { color: @blue-600; @@ -236,7 +296,7 @@ div.highlight { font-style: normal; content: "Copy to clipboard"; position: absolute; - left: 20px; + left: 30px; top: 3px; width: max-content; background: #efefef; @@ -253,6 +313,39 @@ div.highlight { } } } + + &.code { + .code_block { + > div { + display: none; + } + + pre { + border-top: none; + border-radius: .4rem; + } + } + + .copy-to-clipboard { + top: 1.4rem; + } + } +} + +.command+.output, .code+.output { + border-radius: 0; + margin-top: -4.3rem; + .code_block { + > div { + padding: .7rem 1.6rem; + } + } +} + +.output { + .copy-to-clipboard { + display: none; + } } h1, h2, h3, h4, h5, h6 { @@ -299,7 +392,7 @@ pre { overflow: visible; overflow-y: hidden; padding: 2rem; - font-family: 'Menlo'; + font-family: 'Menlo', "Courier New", monospace; font-style: normal; font-weight: 400; font-size: 13px; @@ -337,7 +430,7 @@ pre { aside { grid-area: navigation; width: 28rem; - margin-left: 4rem; + margin-left: 2rem; margin-right: 5.6rem; @media @desktop-wide-down { margin-right: 1.6rem; @@ -362,3 +455,25 @@ article { margin-right: 0 !important; } } + +#scrollToTopBtn { + position: fixed; + bottom: 4rem; + right: 3.2rem; + height: 4.4rem; + width: 4.4rem; + background-color: #aaa; + color: #fff; + border: none; + border-radius: 50%; + cursor: pointer; + transform: scale(0); + transition: all .6s ease-out 0s; + i { + font-size: 1.6rem; + } + &.show { + transform: scale(1); + transition: all .6s ease-in 0s; + } +} diff --git a/generator/_assets/styles/less/dropdown.less b/generator/_assets/styles/less/dropdown.less index 8b1b686a6..764af9cf1 100755 --- a/generator/_assets/styles/less/dropdown.less +++ b/generator/_assets/styles/less/dropdown.less @@ -23,7 +23,7 @@ } &:after { - content: url("../media/images/chevron-down.svg"); + content: url("../../../media/images/chevron-down.svg"); position: absolute; right: 9px; top: 50%; @@ -69,7 +69,7 @@ &[selected="selected"] { &:after { - content: url("../media/images/check.svg"); + content: url("../../../media/images/check.svg"); position: absolute; left: 1.4rem; } diff --git a/generator/_assets/styles/less/font.less b/generator/_assets/styles/less/font.less index 57d66fd5e..d323ae67d 100644 --- a/generator/_assets/styles/less/font.less +++ b/generator/_assets/styles/less/font.less @@ -1,56 +1,56 @@ // bootstrap icons -@import 'node_modules/bootstrap-icons/font/bootstrap-icons.css'; +@import '../node_modules/bootstrap-icons/font/bootstrap-icons.css'; // red hat display -@import "node_modules/@fontsource/red-hat-display/300.css"; -@import "node_modules/@fontsource/red-hat-display/300-italic.css"; -@import "node_modules/@fontsource/red-hat-display/400.css"; -@import "node_modules/@fontsource/red-hat-display/400-italic.css"; -@import "node_modules/@fontsource/red-hat-display/500.css"; -@import "node_modules/@fontsource/red-hat-display/500-italic.css"; -@import "node_modules/@fontsource/red-hat-display/600.css"; -@import "node_modules/@fontsource/red-hat-display/600-italic.css"; -@import "node_modules/@fontsource/red-hat-display/700.css"; -@import "node_modules/@fontsource/red-hat-display/700-italic.css"; -@import "node_modules/@fontsource/red-hat-display/800.css"; -@import "node_modules/@fontsource/red-hat-display/800-italic.css"; -@import "node_modules/@fontsource/red-hat-display/900.css"; -@import "node_modules/@fontsource/red-hat-display/900-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/300.css"; +@import "../node_modules/@fontsource/red-hat-display/300-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/400.css"; +@import "../node_modules/@fontsource/red-hat-display/400-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/500.css"; +@import "../node_modules/@fontsource/red-hat-display/500-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/600.css"; +@import "../node_modules/@fontsource/red-hat-display/600-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/700.css"; +@import "../node_modules/@fontsource/red-hat-display/700-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/800.css"; +@import "../node_modules/@fontsource/red-hat-display/800-italic.css"; +@import "../node_modules/@fontsource/red-hat-display/900.css"; +@import "../node_modules/@fontsource/red-hat-display/900-italic.css"; // red hat text -@import "node_modules/@fontsource/red-hat-text/300.css"; -@import "node_modules/@fontsource/red-hat-text/300-italic.css"; -@import "node_modules/@fontsource/red-hat-text/400.css"; -@import "node_modules/@fontsource/red-hat-text/400-italic.css"; -@import "node_modules/@fontsource/red-hat-text/500.css"; -@import "node_modules/@fontsource/red-hat-text/500-italic.css"; -@import "node_modules/@fontsource/red-hat-text/600.css"; -@import "node_modules/@fontsource/red-hat-text/600-italic.css"; -@import "node_modules/@fontsource/red-hat-text/700.css"; -@import "node_modules/@fontsource/red-hat-text/700-italic.css"; +@import "../node_modules/@fontsource/red-hat-text/300.css"; +@import "../node_modules/@fontsource/red-hat-text/300-italic.css"; +@import "../node_modules/@fontsource/red-hat-text/400.css"; +@import "../node_modules/@fontsource/red-hat-text/400-italic.css"; +@import "../node_modules/@fontsource/red-hat-text/500.css"; +@import "../node_modules/@fontsource/red-hat-text/500-italic.css"; +@import "../node_modules/@fontsource/red-hat-text/600.css"; +@import "../node_modules/@fontsource/red-hat-text/600-italic.css"; +@import "../node_modules/@fontsource/red-hat-text/700.css"; +@import "../node_modules/@fontsource/red-hat-text/700-italic.css"; // red hat mono -@import "node_modules/@fontsource/red-hat-mono/300.css"; -@import "node_modules/@fontsource/red-hat-mono/300-italic.css"; -@import "node_modules/@fontsource/red-hat-mono/400.css"; -@import "node_modules/@fontsource/red-hat-mono/400-italic.css"; -@import "node_modules/@fontsource/red-hat-mono/500.css"; -@import "node_modules/@fontsource/red-hat-mono/500-italic.css"; -@import "node_modules/@fontsource/red-hat-mono/600.css"; -@import "node_modules/@fontsource/red-hat-mono/600-italic.css"; -@import "node_modules/@fontsource/red-hat-mono/700.css"; -@import "node_modules/@fontsource/red-hat-mono/700-italic.css"; +@import "../node_modules/@fontsource/red-hat-mono/300.css"; +@import "../node_modules/@fontsource/red-hat-mono/300-italic.css"; +@import "../node_modules/@fontsource/red-hat-mono/400.css"; +@import "../node_modules/@fontsource/red-hat-mono/400-italic.css"; +@import "../node_modules/@fontsource/red-hat-mono/500.css"; +@import "../node_modules/@fontsource/red-hat-mono/500-italic.css"; +@import "../node_modules/@fontsource/red-hat-mono/600.css"; +@import "../node_modules/@fontsource/red-hat-mono/600-italic.css"; +@import "../node_modules/@fontsource/red-hat-mono/700.css"; +@import "../node_modules/@fontsource/red-hat-mono/700-italic.css"; // roboto -@import "node_modules/@fontsource/roboto/100.css"; -@import "node_modules/@fontsource/roboto/100-italic.css"; -@import "node_modules/@fontsource/roboto/300.css"; -@import "node_modules/@fontsource/roboto/300-italic.css"; -@import "node_modules/@fontsource/roboto/400.css"; -@import "node_modules/@fontsource/roboto/400-italic.css"; -@import "node_modules/@fontsource/roboto/500.css"; -@import "node_modules/@fontsource/roboto/500-italic.css"; -@import "node_modules/@fontsource/roboto/700.css"; -@import "node_modules/@fontsource/roboto/700-italic.css"; -@import "node_modules/@fontsource/roboto/900.css"; -@import "node_modules/@fontsource/roboto/900-italic.css"; +@import "../node_modules/@fontsource/roboto/100.css"; +@import "../node_modules/@fontsource/roboto/100-italic.css"; +@import "../node_modules/@fontsource/roboto/300.css"; +@import "../node_modules/@fontsource/roboto/300-italic.css"; +@import "../node_modules/@fontsource/roboto/400.css"; +@import "../node_modules/@fontsource/roboto/400-italic.css"; +@import "../node_modules/@fontsource/roboto/500.css"; +@import "../node_modules/@fontsource/roboto/500-italic.css"; +@import "../node_modules/@fontsource/roboto/700.css"; +@import "../node_modules/@fontsource/roboto/700-italic.css"; +@import "../node_modules/@fontsource/roboto/900.css"; +@import "../node_modules/@fontsource/roboto/900-italic.css"; diff --git a/generator/_assets/styles/less/header.less b/generator/_assets/styles/less/header.less index d8e6b6b4f..386da3c1d 100755 --- a/generator/_assets/styles/less/header.less +++ b/generator/_assets/styles/less/header.less @@ -41,7 +41,7 @@ flex-direction: column; background: #FFFFFF; z-index: 10; - width: 24.3rem; + width: clamp(24.3rem, 50%, 43.3rem); order: 10; right: 0; position: fixed; @@ -121,16 +121,18 @@ width: 28rem; } - &:after { - content: " "; + input[type="submit"] { position: absolute; right: 2.1rem; top: 50%; transform: translateY(-50%); - background-image: url("./../media/images/zoom-in.svg"); + background-image: url("./../../../media/images/zoom-in.svg"); background-repeat: no-repeat; width: 24px; height: 24px; + border: none; + background-color: transparent; + cursor: pointer; } } } @@ -201,7 +203,7 @@ font-weight: 400; font-size: 12px; line-height: 20px; - font-family: 'Roboto'; + font-family: 'Roboto', Arial, sans-serif; } &:after { @@ -226,7 +228,7 @@ font-size: 14px; line-height: 16px; border-top: 1px solid #d1d2d34a; - font-family: 'Roboto'; + font-family: 'Roboto', Arial, sans-serif; &:first-child { border: none; @@ -270,4 +272,4 @@ background-color: rgba(0, 0, 0, 0.3); z-index: 1; cursor: pointer; -} \ No newline at end of file +} diff --git a/generator/_assets/styles/less/home.less b/generator/_assets/styles/less/home.less index 5e8a91260..aa10cf671 100755 --- a/generator/_assets/styles/less/home.less +++ b/generator/_assets/styles/less/home.less @@ -3,7 +3,7 @@ color: @blue-800; font-size: 3.2rem; line-height: 3.6rem; - font-family: "Red Hat Display"; + font-family: "Red Hat Display", Arial, sans-serif; } &-top { diff --git a/generator/_assets/styles/less/menu.less b/generator/_assets/styles/less/menu.less index 0ca8128bb..56c82f8b2 100755 --- a/generator/_assets/styles/less/menu.less +++ b/generator/_assets/styles/less/menu.less @@ -69,7 +69,8 @@ aside { padding-top: 1rem; padding-bottom: 1rem; display: inline-block; - max-width: 90%; + max-width: 96%; + word-break: break-word; } ul { @@ -106,6 +107,9 @@ aside { width: 33rem; z-index: -1; top: 0; + @media @tablet-down{ + width: 38rem; + } } > a { @@ -239,8 +243,7 @@ aside { font-family: bootstrap-icons; position: absolute; right: 2rem; - top: 50%; - transform: translateY(-50%); + top: 1.1rem; color: @gray-500; font-weight: bold; } diff --git a/generator/_assets/styles/less/pages.less b/generator/_assets/styles/less/pages.less index a9c9e8229..a730c8c79 100755 --- a/generator/_assets/styles/less/pages.less +++ b/generator/_assets/styles/less/pages.less @@ -69,23 +69,22 @@ .TOC { position: sticky; top: 12px; - font-family: "Roboto"; - + font-family: "Roboto", Arial, sans-serif; + transition: top 750ms ease 0s; @media @desktop-down { max-width: 28rem; margin-bottom: 2.4rem; } &-title { - font-weight: 400; - font-size: 16px; - line-height: 24px; - border-bottom: 1px solid #E2E2E2; + font-weight: 500; + font-size: 14px; + line-height: 22px; margin-bottom: .6rem; + display: inline-block; @media @desktop-down { font-weight: 500; line-height: 4.5rem; - background: #F8F8FA; padding-left: .8rem; position: relative; cursor: pointer; @@ -93,7 +92,7 @@ content: "\F286"; font-family: bootstrap-icons; position: absolute; - right: 2rem; + right: -2.8rem; top: 50%; transform: translateY(-50%); } @@ -117,56 +116,57 @@ } #TOCbox_list { - background: #F7F7F7; border-radius: 2px; - color: @blue-700; + color: @gray-600; font-weight: 500; font-size: 14px; line-height: 22px; - padding: .8rem 1.2rem; - max-height: 420px; + padding: .8rem 0; overflow: auto; ul { list-style: none; + border-left: 1px solid #E1E1E1; } li { margin-bottom: 8px; + padding-left: 2.4rem; + &:has(.current) { + border-left: 3px solid @blue-700; + transition: border 0.1s linear; + } } a { - color: @blue-700; - font-weight: 500; + color: @gray-600; + font-weight: 400; font-size: 14px; line-height: 22px; text-decoration: none; + display: inline-block; &:hover { - border-bottom: 1px solid @blue-700; + text-decoration: underline; + border: none; + } + + &.current { + color: @blue-700; + font-weight: 700; + margin-left: -.3rem } } } #TOCbox_list .link_h3, #TOCbox_list_mobile .sidr-class-link_h3 { - margin-left: 1rem; - } - - #TOCbox_list .link_h3:before, - #TOCbox_list_mobile .sidr-class-link_h3:before, - #TOCbox_list .link_h4:before, - #TOCbox_list_mobile .sidr-class-link_h4:before { - font-size: 11px; - margin: 0 6px 0 0; - font-family: bootstrap-icons; - content: "\F280"; - color: #000000; + padding-left: 4rem; } #TOCbox_list .link_h4, #TOCbox_list_mobile .sidr-class-link_h4 { - margin-left: 2rem; + padding-left: 5.6rem; } } } diff --git a/generator/_assets/styles/package-lock.json b/generator/_assets/styles/package-lock.json new file mode 100644 index 000000000..1182c13b8 --- /dev/null +++ b/generator/_assets/styles/package-lock.json @@ -0,0 +1,52 @@ +{ + "name": "styles", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@fontsource/red-hat-display": "^5.0.18", + "@fontsource/red-hat-mono": "^5.0.16", + "@fontsource/red-hat-text": "^5.0.16", + "@fontsource/roboto": "^5.0.8", + "bootstrap-icons": "^1.11.2" + } + }, + "node_modules/@fontsource/red-hat-display": { + "version": "5.0.18", + "resolved": "https://registry.npmjs.org/@fontsource/red-hat-display/-/red-hat-display-5.0.18.tgz", + "integrity": "sha512-FiuR+V5UufMgHvoXNr1cJFyvzd31svgCz/pDnlbTjvbdno/SSX5nC+TK4KJ8/fKLzPSAoQ5obx0sq5H/nZEF/w==" + }, + "node_modules/@fontsource/red-hat-mono": { + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/@fontsource/red-hat-mono/-/red-hat-mono-5.0.16.tgz", + "integrity": "sha512-TYJQOiqgvmfvVqRdZ1L2saLAXUoV7YfJXUnAqb8pMWttFEzmqi0H6qNtN0RxhwYpmVDLWgLF0NtAvFaBW2lfWg==" + }, + "node_modules/@fontsource/red-hat-text": { + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/@fontsource/red-hat-text/-/red-hat-text-5.0.16.tgz", + "integrity": "sha512-FDcRUlNtenKhlNOXz2oHZ7QaHDlW3D/RXasUaFNttjuWPcL/9tVsze5ApEiz9KTY64BtU6KaKyRRLDJ1ho3r7w==" + }, + "node_modules/@fontsource/roboto": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.8.tgz", + "integrity": "sha512-XxPltXs5R31D6UZeLIV1td3wTXU3jzd3f2DLsXI8tytMGBkIsGcc9sIyiupRtA8y73HAhuSCeweOoBqf6DbWCA==" + }, + "node_modules/bootstrap-icons": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.2.tgz", + "integrity": "sha512-TgdiPv+IM9tgDb+dsxrnGIyocsk85d2M7T0qIgkvPedZeoZfyeG/j+yiAE4uHCEayKef2RP05ahQ0/e9Sv75Wg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + } + } +} diff --git a/generator/_assets/styles/package.json b/generator/_assets/styles/package.json new file mode 100644 index 000000000..e1e4c65e4 --- /dev/null +++ b/generator/_assets/styles/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "@fontsource/red-hat-display": "^5.0.18", + "@fontsource/red-hat-mono": "^5.0.16", + "@fontsource/red-hat-text": "^5.0.16", + "@fontsource/roboto": "^5.0.8", + "bootstrap-icons": "^1.11.2" + } +} diff --git a/generator/_config.yml b/generator/_config.yml index dfa2b827d..413ef2fad 100644 --- a/generator/_config.yml +++ b/generator/_config.yml @@ -4,7 +4,7 @@ safe: false plugins: ./_plugins/ # baseurl: /docs/master/ git-repository: github.com/cfengine/documentation -git-branch: "master" +git-branch: "3.21" #source: ./pages/ #destination: #layouts: ./_layouts/ @@ -21,7 +21,7 @@ CFE_manuals_version: "3.21" cfengine: branch: "3.21" core_branch: "3.21" - latest_patch_release: 0 + latest_patch_release: 8 latest_package_build: 1 vagrant_package_build: 1 masterfiles_branch: "3.21.x" @@ -31,10 +31,10 @@ Template: line_numbers: true vagrant: - version: "2.2.19" + version: "2.4.9" virtualbox: - version: "6.1.32" + version: "7.1.8" paginate: 500 @@ -46,5 +46,5 @@ asset_pipeline: bundle: true # Default = true compress: true # Default = true output_path: assets # Default = assets - display_path: docs/3.20/assets # Default = nil + display_path: docs/3.21/assets # Default = nil gzip: false # Default = false diff --git a/generator/_includes/footer.html b/generator/_includes/footer.html index 03f1caed7..a86a93811 100755 --- a/generator/_includes/footer.html +++ b/generator/_includes/footer.html @@ -4,19 +4,12 @@
-{% javascript_asset_tag footer %} -- _assets/js/google_analytics_search.js -- _assets/js/jquery-1.9.1.min.js -- _assets/js/jquery-migrate-1.2.1.min.js -- _assets/js/jquery.sidr.min.js -- _assets/js/jquery.hammer.min.js -- _assets/js/custom.js -- _assets/js/dropdown.js -{% endjavascript_asset_tag %} + + diff --git a/generator/_includes/head.html b/generator/_includes/head.html index 49efe7e10..8ddcb1840 100644 --- a/generator/_includes/head.html +++ b/generator/_includes/head.html @@ -25,7 +25,5 @@ - {% css_asset_tag global %} - - _assets/css/styles.min.css - {% endcss_asset_tag %} + diff --git a/generator/_includes/header_nav.html b/generator/_includes/header_nav.html index fa2071281..216bc9d8c 100755 --- a/generator/_includes/header_nav.html +++ b/generator/_includes/header_nav.html @@ -9,6 +9,7 @@ diff --git a/generator/_layouts/default.html b/generator/_layouts/default.html index 602638ccd..e172234bf 100644 --- a/generator/_layouts/default.html +++ b/generator/_layouts/default.html @@ -48,7 +48,7 @@

diff --git a/generator/_plugins/redcarpet2_markdown.rb b/generator/_plugins/redcarpet2_markdown.rb index 2146a327a..bb2de7693 100644 --- a/generator/_plugins/redcarpet2_markdown.rb +++ b/generator/_plugins/redcarpet2_markdown.rb @@ -6,21 +6,52 @@ PYGMENTS_CACHE_DIR = File.expand_path('../../_cache', __FILE__) FileUtils.mkdir_p(PYGMENTS_CACHE_DIR) +COMMAND_TYPE = "command" +OUTPUT_TYPE = "output" +FILE_TYPE = "file" +CODE_TYPE = "code" +DEFAULT_LANGUAGE = "text" + class Redcarpet2Markdown < Redcarpet::Render::HTML def block_code(code, lang) - lang = lang || "text" + lang = lang || DEFAULT_LANGUAGE path = File.join(PYGMENTS_CACHE_DIR, "#{lang}-#{Digest::MD5.hexdigest code}.html") + meta_data = process_meta_data(code) + if lang == COMMAND_TYPE || lang == OUTPUT_TYPE + meta_data = [lang] + lang = DEFAULT_LANGUAGE + elsif meta_data[0] == FILE_TYPE || meta_data[0] == OUTPUT_TYPE + code = code.lines.to_a[1..-1].join #remove the first meta-line from the code + end cache(path) do colorized = Albino.colorize(code, lang.downcase) - add_code_tags(colorized, lang) + add_code_tags(colorized, lang, meta_data) end end - def add_code_tags(code, lang) + def add_code_tags(code, lang, meta_data) + code + .sub( + /
/,
+      "
#{meta_data[1] || meta_data[0]}
+
"
+      )
+    .sub(/<\/pre>/, "
") + .sub(/class="highlight"/, "class=\"highlight #{meta_data[0]}\"") - code.sub(/
/, "
").
-      sub(/<\/pre>/, "
") + end + + def process_meta_data(code) + firstLine = code.lines.first ? code.lines.first.strip.strip : "" + fileRegex = /^\[(file=)(?.*)\]$/ + if fileRegex =~ firstLine + file = firstLine.match(fileRegex)[:file] + return FILE_TYPE, file + elsif /^\[output\]$/ =~ firstLine + return OUTPUT_TYPE, nil + end + return CODE_TYPE, nil end def cache(path) diff --git a/generator/_references.md b/generator/_references.md index 990bd0ca0..24af13648 100644 --- a/generator/_references.md +++ b/generator/_references.md @@ -1,9 +1,8 @@ -[cfengine]: https://cfengine.com "CFEngine Homepage" -[support desk]: https://support.northern.tech "CFEngine - Support Desk" +[support desk]: https://support.northern.tech "CFEngine - Support desk" [professional services]: https://cfengine.com/support/ "CFEngine - Help and Support" [Free25 Forum]: https://groups.google.com/forum/?hl=en&fromgroups#!forum/cfengine-enterprise-free-25 "Free25 Forum" [help-cfengine]: https://groups.google.com/forum/?hl=en&fromgroups#!forum/help-cfengine "Help Forum" -[bug tracker]: http://tracker.mender.io/projects/CFE/issues "Bug Tracker" +[bug tracker]: http://northerntech.atlassian.net/projects/CFE/issues "Bug Tracker" [cfengine blog]: http://cfengine.com/blog "CFEngine - Blog" [learning center]: http://cfengine.com/learn "CFEngine Learning Center" [contact us]: https://cfengine.com/contactUs "CFEngine - Contact Us" @@ -43,8 +42,8 @@ [Append to inputs used by main policy]: reference-masterfiles-policy-framework.html#append-to-inputs-used-by-main-policy [mpf_extra_autorun_inputs]: reference-masterfiles-policy-framework.html#additional-automatically-loaded-inputs [Append to inputs used by update policy]: reference-masterfiles-policy-framework.html#append-to-inputs-used-by-update-policy -[Classes and Decisions]: reference-language-concepts-classes.html -[language-concepts-classes-hard]: reference-language-concepts-classes.html#hard-classes.html "Language Concepts -> Classes and Decisions: Hard classes" +[Classes and decisions]: reference-language-concepts-classes.html +[language-concepts-classes-hard]: reference-language-concepts-classes.html#hard-classes.html "Language concepts -> Classes and decisions: Hard classes" [lib/files.cf]: reference-masterfiles-policy-framework-lib-files [lib/packages.cf]: reference-masterfiles-policy-framework-lib-packages [stdlib-mog]: reference-masterfiles-policy-framework-lib-files.html#mog diff --git a/generator/_scripts/_publish.sh b/generator/_scripts/_publish.sh index 6ed200d3a..d81aed7e8 100755 --- a/generator/_scripts/_publish.sh +++ b/generator/_scripts/_publish.sh @@ -13,22 +13,22 @@ cd $WRKDIR find documentation/generator/pages -name "*.markdown" | xargs rm cp `find documentation/generator/pages -name "*.*"` documentation/generator/_site if [ ! -d documentation/generator/_site ]; then - exit 1 + exit 1 fi OUTPUT=$WRKDIR/output mkdir -p $OUTPUT -# replace absolute style and script links with relative ones. This way, no +# Replace absolute style and script links with relative ones. This way, no # matter how docs will be served (on https://docs.cfengine.com/docs/3.18/ or # http://buildcache.cfengine.com/packages/build-documentation-pr/jenkins-pr-pipeline-7204/output/_site/), # these links will still be valid. cd documentation/generator/_site for source in *.html; do - sed -i "s/]*\)>// - s// - s/\n\n") - - return markdown_lines + markdown_lines = [] + target_anchor = parameters[0] + html_map = config.get("html_map", dict()) + + target_url = html_map.get(target_anchor) + if target_url == None: + print("Invalid redirect target '%s', redirecting to home" % target_anchor) + target_url = "index.html" + + markdown_lines.append('\n\n") + + return markdown_lines diff --git a/generator/_scripts/cfdoc_metadata.py b/generator/_scripts/cfdoc_metadata.py index 7dfb5d946..b0f7ee12a 100644 --- a/generator/_scripts/cfdoc_metadata.py +++ b/generator/_scripts/cfdoc_metadata.py @@ -28,114 +28,131 @@ from os.path import isfile, join from string import ascii_letters, digits + def run(config): - config["syntax_path"] = config["project_directory"] + "/_generated/syntax_map.json" - config["syntax_map"] = json.load(open(config["syntax_path"], 'r')) - - markdown_files = config["markdown_files"] - for file in markdown_files: - processMetaData(file, config) - - # validate that the category tree is consistent, ie that there is an - # index page for every subdirectory. Otherwise, Jekyll bails out - category_tree = config["category_tree"] - for node in category_tree: - branch = category_tree.get(node) - if branch == None: # orphan - print("Orphan in the category tree! Check path to '%s / %s'" % (branch, node)) - exit(1) - last_branch = branch.split("/")[-1] - if last_branch == "": - continue - parent_branch = category_tree.get(last_branch) - if parent_branch == None: # gaps - print("ERROR: Missing index file '%s.markdown'" % (branch)) - exit(2) + config["syntax_path"] = config["project_directory"] + "/_generated/syntax_map.json" + config["syntax_map"] = json.load(open(config["syntax_path"], "r")) + + markdown_files = config["markdown_files"] + for file in markdown_files: + processMetaData(file, config) + + # validate that the category tree is consistent, ie that there is an + # index page for every subdirectory. Otherwise, Jekyll bails out + category_tree = config["category_tree"] + for node in category_tree: + branch = category_tree.get(node) + if branch == None: # orphan + print( + "Orphan in the category tree! Check path to '%s / %s'" % (branch, node) + ) + exit(1) + last_branch = branch.split("/")[-1] + if last_branch == "": + continue + parent_branch = category_tree.get(last_branch) + if parent_branch == None: # gaps + print("ERROR: Missing index file '%s.markdown'" % (branch)) + exit(2) + # parse meta data lines, remove existing header for later reconstruction def parseHeader(lines): - header = {} - - new_lines = [] - in_header = False - for line in lines: - if line.find("---") == 0: - in_header = not in_header - if in_header: # start of header - nothing to see here - continue - else: # end of header - done - return header - if not in_header: - continue - token_list = line.split(":") - if len(token_list) != 2: - print("parseHeader: ERROR in %s - wrong number of tokens" % line) - continue - tag = token_list[0].lstrip().rstrip() - value = token_list[1].lstrip().lstrip('\"').rstrip().rstrip('\"') - header[tag] = value - - return header; + header = {} + + new_lines = [] + in_header = False + for line in lines: + if line.find("---") == 0: + in_header = not in_header + if in_header: # start of header - nothing to see here + continue + else: # end of header - done + return header + if not in_header: + continue + token_list = line.split(":") + if len(token_list) != 2: + print("parseHeader: ERROR in %s - wrong number of tokens" % line) + continue + tag = token_list[0].lstrip().rstrip() + value = token_list[1].lstrip().lstrip('"').rstrip().rstrip('"') + header[tag] = value + + return header + def processMetaData(file_path, config): - category_tree = config.get("category_tree") - if category_tree == None: - category_tree = {} - - in_file = open(file_path,"r") - lines = in_file.readlines() - in_file.close() - - rel_file_path = file_path[len(config["markdown_directory"]) + 1:file_path.rfind('/')] - file_name = os.path.basename(file_path) - file_name = file_name[:file_name.rfind('.')] - - header = parseHeader(lines) - if (not "published" in header) or (header["published"] == "false"): # ignore unpublished content - return - if header.get("layout") != "default": # ignore special pages - return - if not "title" in header: # ignore pages without title, but that's an error at this point - print("ERROR! Page without title: %s" % file_name) - return - - categories = [] - if len(rel_file_path): - categories = rel_file_path.split("/") - categories.append(file_name) - if len(categories) > 1: - category_tree[categories[-1]] = rel_file_path # store each leaf with its path - else: - category_tree[file_name] = "" - categories = ["\"%s\"" % c for c in categories] # quote all entires to avoid ruby keywords - if len(categories) == 1: - category = categories[0] - else: - category = ", ".join(categories) - - if len(rel_file_path): - alias = "%s-%s" % (rel_file_path, file_name) - else: - alias = file_name - - alias = alias.replace("/", "-").lower() - - out_file = open(file_path, "w") - in_header = False - for line in lines: - if line.find("---") == 0: - in_header = not in_header - if not in_header: # write new tags before header is terminated - out_file.write("categories: [%s]\n" % category) - out_file.write("alias: %s.html\n" % alias) - if in_header: # skip hard-coded duplicates - if line.find("categories:") == 0: - continue - if line.find("alias:") == 0: - continue - - out_file.write(line) - - out_file.close() - config["category_tree"] = category_tree + category_tree = config.get("category_tree") + if category_tree == None: + category_tree = {} + + in_file = open(file_path, "r") + lines = in_file.readlines() + in_file.close() + + rel_file_path = file_path[ + len(config["markdown_directory"]) + 1 : file_path.rfind("/") + ] + file_name = os.path.basename(file_path) + file_name = file_name[: file_name.rfind(".")] + + header = parseHeader(lines) + if (not "published" in header) or ( + header["published"] == "false" + ): # ignore unpublished content + return + if header.get("layout") != "default": # ignore special pages + return + if ( + not "title" in header + ): # ignore pages without title, but that's an error at this point + print("ERROR! Page without title: %s" % file_name) + return + + categories = [] + if len(rel_file_path): + categories = rel_file_path.split("/") + categories.append(file_name) + if len(categories) > 1: + category_tree[categories[-1]] = rel_file_path # store each leaf with its path + else: + category_tree[file_name] = "" + categories = [ + '"%s"' % c for c in categories + ] # quote all entires to avoid ruby keywords + if len(categories) == 1: + category = categories[0] + else: + category = ", ".join(categories) + + if len(rel_file_path): + alias = "%s-%s" % (rel_file_path, file_name) + else: + alias = file_name + + alias = alias.replace("/", "-").lower() + + out_file = open(file_path, "w") + in_header = False + did_header = False + for line in lines: + if did_header: + out_file.write(line) + continue + if line.find("---") == 0: + in_header = not in_header + if not in_header: # write new tags before header is terminated + out_file.write("categories: [%s]\n" % category) + out_file.write("alias: %s.html\n" % alias) + did_header = True + if in_header: # skip hard-coded duplicates + if line.find("categories:") == 0: + continue + if line.find("alias:") == 0: + continue + + out_file.write(line) + out_file.close() + config["category_tree"] = category_tree diff --git a/generator/_scripts/cfdoc_patch_header_nav.py b/generator/_scripts/cfdoc_patch_header_nav.py index 462932e7d..b7d9edfca 100644 --- a/generator/_scripts/cfdoc_patch_header_nav.py +++ b/generator/_scripts/cfdoc_patch_header_nav.py @@ -24,27 +24,47 @@ import json import sys + def patch(current_branch): url = "https://docs.cfengine.com/docs/branches.json" response = urllib.request.urlopen(url) data = json.loads(response.read()) with open("_includes/header_nav_options.html", "w") as f: - for branch in data['docs']: - if "(LTS)" not in branch['Title'] and branch['Version'] != "master" and branch['Version'] != current_branch: + for branch in data["docs"]: + if ( + "(LTS)" not in branch["Title"] + and branch["Version"] != "master" + and branch["Version"] != current_branch + ): continue - selected = '' - link = branch['Link'] - if branch['Version'] == current_branch: + selected = "" + link = branch["Link"] + if branch["Version"] == current_branch: selected = ' selected="selected"' - link = 'javascript:void(0);' - print('%s' % (link, selected, branch['Title'].replace('Version ', '')), file=f) + link = "javascript:void(0);" + print( + '%s' + % (link, selected, branch["Title"].replace("Version ", "")), + file=f, + ) print('view all versions', file=f) with open("_includes/versions_list.html", "w") as f: - for branch in data['docs']: - print('
  • %s
  • ' % (branch['Link'], branch['Title'].replace('Version ', '')), file=f) + for branch in data["docs"]: + print( + '
  • %s
  • ' + % (branch["Link"], branch["Title"].replace("Version ", "")), + file=f, + ) with open("_includes/lts_versions_list.html", "w") as f: - for branch in data['docs']: - if "(LTS)" in branch['Title']: - print('
  • %s
  • ' % (branch['Link'], branch['Title'].replace('Version ', 'CFEngine ')), file=f) + for branch in data["docs"]: + if "(LTS)" in branch["Title"]: + print( + '
  • %s
  • ' + % ( + branch["Link"], + branch["Title"].replace("Version ", "CFEngine "), + ), + file=f, + ) diff --git a/generator/_scripts/cfdoc_postprocess.py b/generator/_scripts/cfdoc_postprocess.py index 4f22d9ca6..a2bfe995b 100755 --- a/generator/_scripts/cfdoc_postprocess.py +++ b/generator/_scripts/cfdoc_postprocess.py @@ -29,10 +29,10 @@ config = environment.validate(sys.argv[1]) try: - sourcelinks.run(config) + sourcelinks.run(config) except: - sys.stdout.write(" Exception: ") - print(sys.exc_info()) - exit(1) + sys.stdout.write(" Exception: ") + print(sys.exc_info()) + exit(1) exit(0) diff --git a/generator/_scripts/cfdoc_preprocess.py b/generator/_scripts/cfdoc_preprocess.py index 1b893831d..b6f2a3663 100755 --- a/generator/_scripts/cfdoc_preprocess.py +++ b/generator/_scripts/cfdoc_preprocess.py @@ -37,35 +37,35 @@ qa.initialize(config) try: - metadata.run(config) + metadata.run(config) except: - print("cfdoc_preprocess: Fatal error setting meta data") - sys.stdout.write(" Exception: ") - print(sys.exc_info()) - exit(2) + print("cfdoc_preprocess: Fatal error setting meta data") + sys.stdout.write(" Exception: ") + print(sys.exc_info()) + exit(2) try: - linkresolver.run(config) + linkresolver.run(config) except: - print("cfdoc_preprocess: Fatal error generating link map") - sys.stdout.write(" Exception: ") - print(sys.exc_info()) - exit(3) + print("cfdoc_preprocess: Fatal error generating link map") + sys.stdout.write(" Exception: ") + print(sys.exc_info()) + exit(3) try: - macros.run(config) + macros.run(config) except: - print("cfdoc_macros: Error generating documentation from syntax maps") - sys.stdout.write(" Exception: ") - print(sys.exc_info()) + print("cfdoc_macros: Error generating documentation from syntax maps") + sys.stdout.write(" Exception: ") + print(sys.exc_info()) -try: # update the link map with content added by macros - linkresolver.run(config) +try: # update the link map with content added by macros + linkresolver.run(config) except: - print("cfdoc_preprocess: Fatal error updating link map") - sys.stdout.write(" Exception: ") - print(sys.exc_info()) - exit(4) + print("cfdoc_preprocess: Fatal error updating link map") + sys.stdout.write(" Exception: ") + print(sys.exc_info()) + exit(4) # generate links to known targets linkresolver.apply(config) @@ -73,17 +73,17 @@ # create printable sources from completely pre-processed markdown try: - printsource.run(config) + printsource.run(config) except: - print("cfdoc_printsource: Error generating print-pages") - sys.stdout.write(" Exception: ") - print(sys.exc_info()) + print("cfdoc_printsource: Error generating print-pages") + sys.stdout.write(" Exception: ") + print(sys.exc_info()) try: - patch_header_nav.patch(sys.argv[1]) + patch_header_nav.patch(sys.argv[1]) except: - print("cfdoc_patch_header_nav: Error patching header navigation") - sys.stdout.write(" Exception: ") - print(sys.exc_info()) + print("cfdoc_patch_header_nav: Error patching header navigation") + sys.stdout.write(" Exception: ") + print(sys.exc_info()) exit(0) diff --git a/generator/_scripts/cfdoc_printsource.py b/generator/_scripts/cfdoc_printsource.py index 58dcef753..0c3d7d590 100644 --- a/generator/_scripts/cfdoc_printsource.py +++ b/generator/_scripts/cfdoc_printsource.py @@ -23,162 +23,177 @@ import os import cfdoc_linkresolver as linkresolver + class Page: - def __init__(self): - self.title = str() - self.parent = None - self.childtrees = dict() - self.childlist = list() - self.sorting = None - self.source_filename = None + def __init__(self): + self.title = str() + self.parent = None + self.childtrees = dict() + self.childlist = list() + self.sorting = None + self.source_filename = None + def run(config): - markdown_files = config["markdown_files"] - pagetree = Page() - for markdown_file in markdown_files: - in_file = open(markdown_file, 'r') - lines = in_file.readlines() - in_file.close() - - in_header = False - publish = False - sorting = -1 - title = str() - alias = str() - categories = list() - for line in lines: - if line[:3] == '---': - if in_header: - break; - in_header = True - if in_header: - line = line.lstrip().rstrip() - if line.find('categories: [') == 0: - categories = line[line.find('[') + 1:line.find(']')].split(",") - elif line.find('title: ') == 0: - title = line[line.find(':') + 1:].lstrip().rstrip() - elif line.find('alias: ') == 0: - alias = line[line.find(':') + 1:].lstrip().rstrip() - elif line.find('published: true') == 0: - publish = True - elif line.find('sorting: ') == 0: - sortstring = line[9:] - if sortstring.isdigit(): sorting = int(sortstring) - - if publish and len(categories) > 0: - child = pagetree - count = len(categories) - for category in categories: - category = category.lstrip().rstrip() - parent = child - child = parent.childtrees.get(category) - if child == None: # new branch - child = Page() - child.parent = parent - parent.childtrees[category] = child - parent.childlist.append(child) - if count == 1: # node - child.title = title - child.alias = alias - child.source_filename = markdown_file - child.sorting = sorting - count -= 1 - - new_pages = dict() - print_pages(pagetree, 1, None, new_pages) - for new_page in list(new_pages.keys()): - headers = new_pages[new_page] - in_file = open(new_page, 'r') - lines = in_file.readlines() - in_file.close() - - out_file = open(new_page, 'w') - for line in lines: - if line.find("alias:") == 0: - alias = line[line.find(':') + 1:].lstrip().rstrip() - out_file.write(line) - elif line.find("[%CFEngine_TOC%]") == 0: - out_file.write("# Table of Content\n") - out_file.write("\n") - first = True - for header in headers: - level = header.find(' ') - 1 - if level > 3 or level < 1: - continue - header = header[level + 2:] - - # make sure we start with a proper list - if first and level > 1: - level = 1 - if alias != None: - entry = " " * ((level - 1) * 4) + "* [" + header + "]" - entry += "("+ alias + "#" + linkresolver.headerToAnchor(header) + ")" - else: - entry = header - out_file.write(entry + "\n") - first = False - else: - out_file.write(line) - out_file.close() + markdown_files = config["markdown_files"] + pagetree = Page() + for markdown_file in markdown_files: + in_file = open(markdown_file, "r") + lines = in_file.readlines() + in_file.close() + + in_header = False + publish = False + sorting = -1 + title = str() + alias = str() + categories = list() + for line in lines: + if line[:3] == "---": + if in_header: + break + in_header = True + if in_header: + line = line.lstrip().rstrip() + if line.find("categories: [") == 0: + categories = line[line.find("[") + 1 : line.find("]")].split(",") + elif line.find("title: ") == 0: + title = line[line.find(":") + 1 :].lstrip().rstrip() + elif line.find("alias: ") == 0: + alias = line[line.find(":") + 1 :].lstrip().rstrip() + elif line.find("published: true") == 0: + publish = True + elif line.find("sorting: ") == 0: + sortstring = line[9:] + if sortstring.isdigit(): + sorting = int(sortstring) + + if publish and len(categories) > 0: + child = pagetree + count = len(categories) + for category in categories: + category = category.lstrip().rstrip() + parent = child + child = parent.childtrees.get(category) + if child == None: # new branch + child = Page() + child.parent = parent + parent.childtrees[category] = child + parent.childlist.append(child) + if count == 1: # node + child.title = title + child.alias = alias + child.source_filename = markdown_file + child.sorting = sorting + count -= 1 + + new_pages = dict() + print_pages(pagetree, 1, None, new_pages) + for new_page in list(new_pages.keys()): + headers = new_pages[new_page] + in_file = open(new_page, "r") + lines = in_file.readlines() + in_file.close() + + out_file = open(new_page, "w") + for line in lines: + if line.find("alias:") == 0: + alias = line[line.find(":") + 1 :].lstrip().rstrip() + out_file.write(line) + elif line.find("[%CFEngine_TOC%]") == 0: + out_file.write("# Table of Content\n") + out_file.write("\n") + first = True + for header in headers: + level = header.find(" ") - 1 + if level > 3 or level < 1: + continue + header = header[level + 2 :] + + # make sure we start with a proper list + if first and level > 1: + level = 1 + if alias != None: + entry = " " * ((level - 1) * 4) + "* [" + header + "]" + entry += ( + "(" + + alias + + "#" + + linkresolver.headerToAnchor(header) + + ")" + ) + else: + entry = header + out_file.write(entry + "\n") + first = False + else: + out_file.write(line) + out_file.close() + def print_pages(pages, level, out_file, new_pages): - sorted_pages = sorted(pages.childlist, key=lambda page: page.sorting) - for page in sorted_pages: - if page == None: - continue - if level == 1: - out_filename = page.source_filename - out_filename = out_filename.replace(".markdown", "-printable.markdown") - new_pages[out_filename] = list() - out_file = open(out_filename, "w") - out_file.write("---\n") - out_file.write("layout: printable\n") - out_file.write("title: \"The Complete " + page.title + "\"\n") - out_file.write("published: true\n") - out_file.write("alias: %s-printable.html\n" % page.alias[:page.alias.rfind('.')]) - out_file.write("---\n") - out_file.write("\n") - out_file.write("[%CFEngine_TOC%]\n") - out_file.write("\n") - else: - title = "#" * level - title += " " + page.title - out_file.write(title + "\n\n") - new_pages[out_file.name].append(title) - - new_pages[out_file.name] += print_page(page.source_filename, out_file, level) - - print_pages(page, level +1, out_file, new_pages) + sorted_pages = sorted(pages.childlist, key=lambda page: page.sorting) + for page in sorted_pages: + if page == None: + continue + if level == 1: + out_filename = page.source_filename + out_filename = out_filename.replace(".markdown", "-printable.markdown") + new_pages[out_filename] = list() + out_file = open(out_filename, "w") + out_file.write("---\n") + out_file.write("layout: printable\n") + out_file.write('title: "The Complete ' + page.title + '"\n') + out_file.write("published: true\n") + out_file.write( + "alias: %s-printable.html\n" % page.alias[: page.alias.rfind(".")] + ) + out_file.write("---\n") + out_file.write("\n") + out_file.write("[%CFEngine_TOC%]\n") + out_file.write("\n") + else: + title = "#" * level + title += " " + page.title + out_file.write(title + "\n\n") + new_pages[out_file.name].append(title) + + new_pages[out_file.name] += print_page(page.source_filename, out_file, level) + + print_pages(page, level + 1, out_file, new_pages) + def print_page(page_file, out_file, level): - in_file = open(page_file, 'r') - lines = in_file.readlines() - - out_file.write("\n") - - headers = list() - in_body = True - in_code = False - for line in lines: - if line[:3] == '---': - in_body = not in_body - continue - if line[:3] == '```': - in_code = not in_code - out_file.write(line) - continue - if in_body: - if not in_code: - if line[0] == '#': # increase indent level for header in page, up to level 6 - line = '#' * max(level - 1, 4) + line - if line.find(' ') > 6: - line = line[line.find(' ') - 6:] - if (line.find("exclude-from-toc") == -1 and line.rstrip()[-1] != '#'): - headers.append(line.lstrip().rstrip()) - out_file.write(line) - - out_file.write("\n") - out_file.write("\n") - out_file.write("\n--------\n\n") - out_file.write("\n") - return headers + in_file = open(page_file, "r") + lines = in_file.readlines() + + out_file.write("\n") + + headers = list() + in_body = True + in_code = False + for line in lines: + if line[:3] == "---": + in_body = not in_body + continue + if line[:3] == "```": + in_code = not in_code + out_file.write(line) + continue + if in_body: + if not in_code: + if ( + line[0] == "#" + ): # increase indent level for header in page, up to level 6 + line = "#" * max(level - 1, 4) + line + if line.find(" ") > 6: + line = line[line.find(" ") - 6 :] + if line.find("exclude-from-toc") == -1 and line.rstrip()[-1] != "#": + headers.append(line.lstrip().rstrip()) + out_file.write(line) + + out_file.write("\n") + out_file.write("\n") + out_file.write("\n--------\n\n") + out_file.write("\n") + return headers diff --git a/generator/_scripts/cfdoc_qa.py b/generator/_scripts/cfdoc_qa.py index bbe637811..8c6c9009f 100644 --- a/generator/_scripts/cfdoc_qa.py +++ b/generator/_scripts/cfdoc_qa.py @@ -24,67 +24,92 @@ import sys from time import gmtime, strftime + def initialize(config): - config["log_file"] = config["markdown_directory"] + "/cfdoc_log.markdown" - if os.path.exists(config["log_file"]): - os.remove(config["log_file"]) - logfile = open(config["log_file"], "w") - logfile.write("---\n") - logfile.write("layout: printable\n") - logfile.write("title: \"Documentation Issues\"\n") - logfile.write("published: true\n") - logfile.write("alias: cfdoc_log.html\n") - logfile.write("---\n") - logfile.write("\n") - logfile.write("Documentation generated at %s GMT\n" % strftime("%Y-%m-%d %H:%M:%S", gmtime())) - logfile.write("\n") - logfile.write("# Logging\n") - logfile.write("\n") - logfile.close() + config["log_file"] = config["markdown_directory"] + "/cfdoc_log.markdown" + if os.path.exists(config["log_file"]): + os.remove(config["log_file"]) + logfile = open(config["log_file"], "w") + logfile.write("---\n") + logfile.write("layout: printable\n") + logfile.write('title: "Documentation Issues"\n') + logfile.write("published: true\n") + logfile.write("alias: cfdoc_log.html\n") + logfile.write("---\n") + logfile.write("\n") + logfile.write( + "Documentation generated at %s GMT\n" % strftime("%Y-%m-%d %H:%M:%S", gmtime()) + ) + logfile.write("\n") + logfile.write("# Logging\n") + logfile.write("\n") + logfile.close() def OpenLogFile(config): - logfile = open(config["log_file"], "a") - return logfile + logfile = open(config["log_file"], "a") + return logfile + def LogProcessStart(config, string): - logfile = OpenLogFile(config) - logfile.write("\n") - logfile.write("### %s\n" % string) - logfile.write("\n") - logfile.close() + logfile = OpenLogFile(config) + logfile.write("\n") + logfile.write("### %s\n" % string) + logfile.write("\n") + logfile.close() + def LogMissingDocumentation(config, element, strings, location): - logfile = OpenLogFile(config) - if not element.startswith("`"): - element = "`%s`" % element - logfile.write("* %s:\n" % element) - if len(strings): - logfile.write(" * Errors:\n") - for string in strings: - logfile.write(" * **%s**\n" % string) - if len(location): - logfile.write(" * Source location: `%s`\n" % location) - logfile.write(" * Triggered by: `%s` (%d)\n" % (os.path.relpath(config["context_current_file"]), config["context_current_line_number"])) - logfile.close() + logfile = OpenLogFile(config) + if not element.startswith("`"): + element = "`%s`" % element + logfile.write("* %s:\n" % element) + if len(strings): + logfile.write(" * Errors:\n") + for string in strings: + logfile.write(" * **%s**\n" % string) + if len(location): + logfile.write(" * Source location: `%s`\n" % location) + logfile.write( + " * Triggered by: `%s` (%d)\n" + % ( + os.path.relpath(config["context_current_file"]), + config["context_current_line_number"], + ) + ) + logfile.close() + def Log(config, string): - # Prepend the error string as a general error without context of current process - logfile = open(config["log_file"], 'r') - original = logfile.readlines() - logfile.close() + # Prepend the error string as a general error without context of current process + logfile = open(config["log_file"], "r") + original = logfile.readlines() + logfile.close() - logfile = open(config["log_file"], 'w') - line_offset = 0 - for line in original: - logfile.write(line) - line_offset += 1 - if line == "# Logging\n": - break + logfile = open(config["log_file"], "w") + line_offset = 0 + for line in original: + logfile.write(line) + line_offset += 1 + if line == "# Logging\n": + break - logfile.write("\n* %s\n" % string) - logfile.write(" * Triggered by: `%s` (%d)\n" % (os.path.relpath(config["context_current_file"]), config["context_current_line_number"])) - print("%s (%d): %s" % (os.path.relpath(config["context_current_file"]), config["context_current_line_number"], string)) + logfile.write("\n* %s\n" % string) + logfile.write( + " * Triggered by: `%s` (%d)\n" + % ( + os.path.relpath(config["context_current_file"]), + config["context_current_line_number"], + ) + ) + print( + "%s (%d): %s" + % ( + os.path.relpath(config["context_current_file"]), + config["context_current_line_number"], + string, + ) + ) - logfile.writelines(original[line_offset:]) - logfile.close() + logfile.writelines(original[line_offset:]) + logfile.close() diff --git a/generator/_scripts/cfdoc_sourcelinks.py b/generator/_scripts/cfdoc_sourcelinks.py index 753c52c45..f3dfe74cb 100644 --- a/generator/_scripts/cfdoc_sourcelinks.py +++ b/generator/_scripts/cfdoc_sourcelinks.py @@ -23,6 +23,7 @@ import os import re + def run(config): verifyLinkRegex(unresolvedLinkRegex()) verifyMacroRegex(unexpandedMacroRegex()) @@ -34,20 +35,26 @@ def run(config): if error_count: raise Exception("%d errors while processing HTML files" % error_count) + def verifyRegex(regex, tests): for test in tests: line = test[0] expected = test[1] actual = regex.search(line) != None if actual != expected: - print("Programming error: regex '%s' doesn't match '%s' correctly!" % (regex, line)) + print( + "Programming error: regex '%s' doesn't match '%s' correctly!" + % (regex, line) + ) print(" expected result: %s" % expected) exit(-1) + def unresolvedLinkRegex(): # should include `:` behind closing bracket, but leads to false positives return re.compile("(^|\\s+|>)\\[.+?\\]\\[.*?\\](\\s|[,\\.;,]|$||)") + def verifyLinkRegex(regex): tests = [] # uresolved links @@ -56,25 +63,27 @@ def verifyLinkRegex(regex): tests.append(("text [a][b].", True)) tests.append(("text [a][b],", True)) tests.append(("text [a][b];", True)) - tests.append(("text [a][b]:", False)) # KNOWN ISSUE - tests.append(("text [a][]", True)) # shorthand - tests.append(("
  • [a][b]\n", True)) # bullet list - tests.append(("
  • [a][b]
  • ", True)) # bullet list - tests.append(("text [a][b]", True)) # missing lineend and eof + tests.append(("text [a][b]:", False)) # KNOWN ISSUE + tests.append(("text [a][]", True)) # shorthand + tests.append(("
  • [a][b]\n", True)) # bullet list + tests.append(("
  • [a][b]
  • ", True)) # bullet list + tests.append(("text [a][b]", True)) # missing lineend and eof # ok - tests.append(("a[a][b]\n", False)) # Array - tests.append(("[][]\n", False)) # Not markdown - tests.append(("[][a]\n", False)) # Not markdown - tests.append(("[a][b][c]\n", True)) # enumeration - KNOWN ISSUE - tests.append(("[a][b]text\n", False)) # Something else - tests.append(("[a][b]", False)) # code stuff + tests.append(("a[a][b]\n", False)) # Array + tests.append(("[][]\n", False)) # Not markdown + tests.append(("[][a]\n", False)) # Not markdown + tests.append(("[a][b][c]\n", True)) # enumeration - KNOWN ISSUE + tests.append(("[a][b]text\n", False)) # Something else + tests.append(("[a][b]", False)) # code stuff verifyRegex(regex, tests) + def unexpandedMacroRegex(): return re.compile("\\[%CFEngine_.*%\\]") + def verifyMacroRegex(regex): tests = [] # unexpanded macro @@ -86,16 +95,17 @@ def verifyMacroRegex(regex): verifyRegex(regex, tests) -def addLinkToSource(file_name,config): - in_file = open(file_name,"r") + +def addLinkToSource(file_name, config): + in_file = open(file_name, "r") lines = in_file.readlines() in_file.close() - source_file = file_name[config["markdown_directory"].__len__():] + source_file = file_name[config["markdown_directory"].__len__() :] html_file = "" for line in lines: if line.find("alias:") == 0: - html_file = line.split('alias: ') + html_file = line.split("alias: ") html_file = html_file[1].rstrip() break if line.find("layout: printable") == 0: @@ -108,21 +118,26 @@ def addLinkToSource(file_name,config): unexpanded_macro = unexpandedMacroRegex() error_count = 0 - html_file = config['CFE_DIR'] + "/" + html_file + html_file = config["CFE_DIR"] + "/" + html_file try: in_file = open(html_file, "r") lines = in_file.readlines() in_file.close() except: print("cfdoc_sourcelinks: Error opening " + html_file) - return 0 # tolerate missing HTML files + return 0 # tolerate missing HTML files new_html_file = html_file + ".new" out_file = open(new_html_file, "w") for line in lines: - line = line.replace("\">markdown source]", source_file + "\">markdown source]") + line = line.replace( + '">markdown source]', source_file + '">markdown source]' + ) if unresolved_link.search(line) != None: - print("Unresolved link in '%s', html-line '%s'\n\n Perhaps you need to add an entry to to _references.md in the documentation/generator repository" % (file_name, line)) + print( + "Unresolved link in '%s', html-line '%s'\n\n Perhaps you need to add an entry to to _references.md in the documentation/generator repository" + % (file_name, line) + ) error_count += 1 if unexpanded_macro.search(line) != None: print("Unexpanded macro in '%s', html-line '%s'\n" % (file_name, line)) @@ -130,5 +145,5 @@ def addLinkToSource(file_name,config): out_file.write(line) out_file.close() - os.rename(new_html_file,html_file) + os.rename(new_html_file, html_file) return error_count diff --git a/generator/_scripts/starter_pack-build-docs.sh b/generator/_scripts/starter_pack-build-docs.sh index 0396933e2..bcf9f4d88 100644 --- a/generator/_scripts/starter_pack-build-docs.sh +++ b/generator/_scripts/starter_pack-build-docs.sh @@ -14,11 +14,11 @@ $WRKDIR/documentation/generator/_scripts/cfdoc_bootstrap.py master if dpkg --get-selections | grep -q "^cfengine-nova-hub[[:space:]]*install$" >/dev/null; then echo Found cfengine-nova-hub package installed, skipping build else - echo Did not find package cfengine-nova-hub installed, trying to build from source - # Prepare core for syntax docs - cd /northern.tech/cfengine/core - ./configure - make + echo Did not find package cfengine-nova-hub installed, trying to build from source + # Prepare core for syntax docs + cd /northern.tech/cfengine/core + ./configure + make fi export WRKDIR=/northern.tech/cfengine diff --git a/generator/build/Dockerfile b/generator/build/Dockerfile index 3b83b9691..530fe5b5d 100644 --- a/generator/build/Dockerfile +++ b/generator/build/Dockerfile @@ -14,7 +14,7 @@ RUN chown -R jenkins:jenkins /home/jenkins COPY install.sh / USER jenkins WORKDIR /home/jenkins -RUN bash -x /install.sh +RUN bash -x /install.sh 2>&1 | tee /install.sh.log # This is where our repos will be WORKDIR /nt diff --git a/generator/build/README.md b/generator/build/README.md index c3af1a309..8a392e579 100644 --- a/generator/build/README.md +++ b/generator/build/README.md @@ -14,14 +14,13 @@ You will need to have the following repos checked out: * enterprise (used for changelog) * masterfiles (used to document masterfies) * documentation -* documentation/generator (this repo) Usage ----- If you have buildah installed: -1. clone the above repos +1. clone the above repos (run `clone.sh`) 2. export the following env variables: @@ -30,11 +29,11 @@ If you have buildah installed: * `$PACKAGE_JOB` - where to take CFEngine HUB package from, a dir at http://buildcache.cloud.cfengine.com/packages/, - usually testing-pr + usually `testing-pr` * `$PACKAGE_UPLOAD_DIRECTORY` - where to take CFEngine HUB package from, a dir at http://buildcache.cloud.cfengine.com/packages/testing-pr/, - for example, jenkins-master-nightly-pipeline-943 + for example, `jenkins-master-nightly-pipeline-943` * `$PACKAGE_BUILD` - RELEASE of the build to be downloaded, usually 1 diff --git a/generator/build/clone.sh b/generator/build/clone.sh new file mode 100755 index 000000000..95aa156b5 --- /dev/null +++ b/generator/build/clone.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +for repo in core nova enterprise masterfiles documentation; do + git clone "git@github.com:cfengine/$repo.git" +done diff --git a/generator/build/install.sh b/generator/build/install.sh index f86f7580b..224f9fba2 100644 --- a/generator/build/install.sh +++ b/generator/build/install.sh @@ -49,17 +49,18 @@ curl -O https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installe curl -O https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer.asc if gpg2 --verify rvm-installer.asc; then - bash rvm-installer --autolibs=read-fail --ignore-dotfiles stable + bash rvm-installer --autolibs=read-fail --ignore-dotfiles stable else - echo "Ruby Version Manager signature check fail." - echo "Github is hacked, or trying to hack us, or our script is wrong. Aborting everything" - exit 1 + echo "Ruby Version Manager signature check fail." + echo "Github is hacked, or trying to hack us, or our script is wrong. Aborting everything" + exit 1 fi # rvm commands are insane scripts which pollut output # so instead of set -x we just echo each command ourselves set +x echo "+ source ~/.rvm/scripts/rvm" +# shellcheck disable=SC1090 source ~/.rvm/scripts/rvm echo "+ rvm_rubygems_version=none rvm install --autolibs=read-only ruby-1.9.3-p551 -C --without-openssl" @@ -70,9 +71,9 @@ gem install jekyll-asset-pipeline --version 0.1.6 gem install closure-compiler --version 1.1.8 gem install yui-compressor --version 0.9.6 gem install albino --version 1.3.3 +gem install execjs --version 1.4.0 gem install redcarpet --version 2.2.2 gem install uglifier --version 1.3.0 -gem install execjs --version 1.4.0 gem install sanitize --version 2.0.3 cat > /tmp/jekyll-0.12.1-cfengine.patch <.*_\1_' | sort -rn | while read -r build; do - # $build is something like jenkins-master-nightly-pipeline-962 - # verify that it has a deb file - url="$BUILDCACHE_URL/$build/PACKAGES_HUB_x86_64_linux_ubuntu_16/" - if curl --silent "$url" | grep -qF '.deb'; then - echo "$build" - break - fi + # $build is something like jenkins-master-nightly-pipeline-962 + # verify that it has a deb file + url="$BUILDCACHE_URL/$build/PACKAGES_HUB_x86_64_linux_ubuntu_16/" + if curl --silent "$url" | grep -qF '.deb'; then + echo "$build" + break + fi done diff --git a/generator/build/main.sh b/generator/build/main.sh index 11238ca46..16513dbe9 100644 --- a/generator/build/main.sh +++ b/generator/build/main.sh @@ -1,21 +1,30 @@ #!/bin/bash if [ "$#" != 4 ]; then - echo "Pass 4 args, please:" - echo BRANCH - echo PACKAGE_JOB - echo PACKAGE_UPLOAD_DIRECTORY - echo PACKAGE_BUILD - exit 1 + echo "Pass 4 args, please:" + echo BRANCH + echo PACKAGE_JOB + echo PACKAGE_UPLOAD_DIRECTORY + echo PACKAGE_BUILD + exit 1 fi +echo "$(basename "$0"): Diagnostic facts about execution environment:" +echo "======" +whoami +cat /etc/os-release +free -h +df -h +uname -a +echo "======" + + export BRANCH=$1 export PACKAGE_JOB=$2 export PACKAGE_UPLOAD_DIRECTORY=$3 export PACKAGE_BUILD=$4 export JOB_TO_UPLOAD=$PACKAGE_JOB -export FLAG_FILE_URL="http://buildcache.cfengine.com/packages/$PACKAGE_JOB/$PACKAGE_UPLOAD_DIRECTORY/PACKAGES_HUB_x86_64_linux_ubuntu_18/core-commitID" export NO_OUTPUT_DIR=1 env @@ -24,35 +33,36 @@ set -x # take ownersip of all files sudo chown -R jenkins:jenkins . -export WRKDIR=`pwd` +WRKDIR=$(pwd) +export WRKDIR -cd $WRKDIR/documentation/generator +cd "$WRKDIR"/documentation/generator -### download CFEngine ### +### Download CFEngine: # c https://github.com/cfengine/misc/blob/master/vagrant_quickstart/build.sh function fetch_file() { - # $1 -- URL to fetch - # $2 -- destination - # $3 -- number of tries (with 10s pauses) [optional, default=1] - local target="$1" - local destination="$2" - local tries=1 - if [ $# -gt 2 ]; then - tries="$3" - fi - local success=1 # 1 means False in bash, 0 means True - set +e - for i in `seq 1 $tries`; do - wget "$target" -O "$destination" && success=0 && break - if [ $i -lt $tries ]; then - sleep 10s + # $1 -- URL to fetch + # $2 -- destination + # $3 -- number of tries (with 10s pauses) [optional, default=1] + local target="$1" + local destination="$2" + local tries=1 + if [ $# -gt 2 ]; then + tries="$3" fi - done - set -e - return $success + local success=1 # 1 means False in bash, 0 means True + set +e + for i in $(seq 1 "$tries"); do + wget "$target" -O "$destination" && success=0 && break + if [ "$i" -lt "$tries" ]; then + sleep 10s + fi + done + set -e + return $success } set -ex @@ -62,40 +72,59 @@ test ! -z "$JOB_TO_UPLOAD" test ! -z "$PACKAGE_UPLOAD_DIRECTORY" test ! -z "$PACKAGE_BUILD" -BUILDCACHE=http://buildcache.cfengine.com -echo "Waiting for flag file to appear" -for i in `seq 30`; do - wget -O- $FLAG_FILE_URL && break || true - echo "Waiting 10 sec" - sleep 10 -done -# check if flag file is there - if not, script will fail here -wget -O- $FLAG_FILE_URL -echo "Detecting version" -HUB_DIR_NAME=PACKAGES_HUB_x86_64_linux_ubuntu_18 -HUB_DIR_URL="http://buildcache.cfengine.com/packages/$PACKAGE_JOB/$PACKAGE_UPLOAD_DIRECTORY/$HUB_DIR_NAME/" -HUB_PACKAGE_NAME="$(wget $HUB_DIR_URL -O- | sed '/deb/!d;s/.*"\([^"]*\.deb\)".*/\1/')" - -fetch_file "$HUB_DIR_URL$HUB_PACKAGE_NAME" "cfengine-nova-hub.deb" 12 +echo "Install hub package" +if [ "$PACKAGE_JOB" = "cf-remote" ]; then + echo "Install using cf-remote" + sudo apt update -y + sudo apt install -y python3-venv pipx + pipx install cf-remote + export PATH="$HOME/.local/bin:$PATH" + # shellcheck source=/dev/null + source /etc/os-release + rm -rf ~/.cfengine/cf-remote/packages # to ensure we only get one + # in case of LTS branches like 3.21 (without .x since we are in documentation repo) need to add on .x + if [ "$(expr "$BRANCH" : ".*.x")" = 0 ]; then + if [ "$BRANCH" = "master" ]; then + _VERSION=master + else + _VERSION="$BRANCH".x + fi + else + _VERSION="$BRANCH" # in case someone copy/pastes this to a repo besides documentation + fi + cf-remote --version "$_VERSION" download "${ID}$(echo "${VERSION_ID}" | cut -d. -f1)" hub "$(uname -m)" + find "$HOME/.cfengine" # debug + find "$HOME/.cfengine" -name '*.deb' -print0 | xargs -0 -I{} cp {} cfengine-nova-hub.deb +else + echo "Installing with old-style fetch_file function" + HUB_DIR_NAME=PACKAGES_HUB_x86_64_linux_ubuntu_22 + HUB_DIR_URL="http://buildcache.cfengine.com/packages/$PACKAGE_JOB/$PACKAGE_UPLOAD_DIRECTORY/$HUB_DIR_NAME/" + HUB_PACKAGE_NAME="$(wget "$HUB_DIR_URL" -O- | sed '/\.deb/!d;s/.*"\([^"]*\.deb\)".*/\1/')" + + fetch_file "$HUB_DIR_URL$HUB_PACKAGE_NAME" "cfengine-nova-hub.deb" 12 +fi sudo apt-get -y purge cfengine-nova-hub || true sudo rm -rf /*/cfengine -# unpack +# we unpack the hub package instead of installing to get around trouble with the package trying to start up services in a container which doesn't work all that well (yet, 2025) sudo dpkg --unpack cfengine-nova-hub.deb +rm cfengine-nova-hub.deb + +# TODO: why copy the masterfiles from the package over the top of one we checked out which could have changes from a PR? sudo cp -a /var/cfengine/share/NovaBase/masterfiles "$WRKDIR" sudo chmod -R a+rX "$WRKDIR"/masterfiles # write current branch into the config.yml -echo "branch: $BRANCH" >> $WRKDIR/documentation/generator/_config.yml +echo "branch: $BRANCH" >> "$WRKDIR"/documentation/generator/_config.yml # Generate syntax data ./_regenerate_json.sh || exit 4 # Preprocess Documentation with custom macros -./_scripts/cfdoc_preprocess.py $BRANCH || exit 5 +./_scripts/cfdoc_preprocess.py "$BRANCH" || exit 5 # rvm commands are insane scripts which pollut output # so instead of set -x we just echo each command ourselves @@ -103,25 +132,23 @@ set +x # since May 14 2019, we need this to run jekyll. IDK why. echo "+ source ~/.rvm/scripts/rvm" +# shellcheck disable=SC1090 source ~/.rvm/scripts/rvm echo "+ rvm --default use 1.9.3-p551" rvm --default use 1.9.3-p551 echo "+ source ~/.profile" ls -lah ~ +# shellcheck disable=SC1090 test -f ~/.profile && source ~/.profile echo "+ source ~/.rvm/scripts/rvm" +# shellcheck disable=SC1090 source ~/.rvm/scripts/rvm export LC_ALL=C.UTF-8 -$(which npx) -y -p less lessc --compress $WRKDIR/documentation/generator/_assets/styles/cfengine.less $WRKDIR/documentation/generator/_assets/css/styles.min.css - # finally, run actual jekyll echo "+ bash -x ./_scripts/_run_jekyll.sh $BRANCH || exit 6" -bash -x ./_scripts/_run_jekyll.sh $BRANCH || exit 6 +bash -x ./_scripts/_run_jekyll.sh "$BRANCH" || exit 6 -cd $WRKDIR/documentation/generator/build/search -$(which npm) i -$(which node) createIndex.js -cp -rf ./searchIndex ./../../_site/assets/ -npm install --prefix $WRKDIR/documentation/generator/_site/assets bootstrap-icons @fontsource/red-hat-display @fontsource/red-hat-text @fontsource/red-hat-mono @fontsource/roboto +cd "$WRKDIR"/documentation/generator +npm run build diff --git a/generator/build/run.sh b/generator/build/run.sh index a11aad79b..cb2a9afa5 100644 --- a/generator/build/run.sh +++ b/generator/build/run.sh @@ -3,25 +3,35 @@ set -ex trap "echo FAILURE" ERR -if ! buildah inspect docs-revamp-22 >/dev/null 2>&1; then - buildah build-using-dockerfile -t docs-revamp-22 documentation/generator/build +image_name=docs-revamp-22 +if ! buildah inspect "$image_name" >/dev/null 2>&1; then + buildah build-using-dockerfile -t "$image_name" documentation/generator/build fi -# current path must have the following repos cloned: +# Current path must have the following repos cloned: # * core (used for changelog, examples) # * nova (used for changelog) # * enterprise (used for changelog) # * masterfiles (used to document masterfies) # * documentation (this repo) -# these env vars must be defined -true "${BRANCH?undefined}" +# The PACKAGE* vars are not needed for fast-build jobs as they use cf-remote --version $BRANCH install +# We still require them to have a value but by current convention (until cf-remote --version testing-pr-build-number works) we set them to cf-remote in documentation/Jenkinsfile true "${PACKAGE_JOB?undefined}" true "${PACKAGE_UPLOAD_DIRECTORY?undefined}" true "${PACKAGE_BUILD?undefined}" -c=$(buildah from -v $PWD:/nt docs-revamp-22) -trap "buildah run $c bash -c 'sudo chmod -R a+rwX /nt'; buildah rm $c >/dev/null" EXIT -buildah run $c bash -x documentation/generator/build/main.sh $BRANCH $PACKAGE_JOB $PACKAGE_UPLOAD_DIRECTORY $PACKAGE_BUILD -buildah run $c bash -x documentation/generator/_scripts/_publish.sh $BRANCH +# figure out BRANCH from jenkins environment variables +if [ -n "$PR_BASE" ]; then + # PR_BASE comes from documentation/Jenkinsfile and ${pullRequest.base} + BRANCH="$PR_BASE" +elif [ -n "$BRANCH_NAME" ]; then + # jenkins, for pull requests this will be e.g. PR- so not used + # for non-pull reqeusts this will be master, 3.24.x, etc + BRANCH="$BRANCH_NAME" +fi +c=$(buildah from -v "$PWD":/nt "$image_name") +trap 'buildah run "$c" bash -c "sudo chown -R root:root /nt; sudo chmod -R a+rwX /nt"; buildah rm "$c" >/dev/null' EXIT +buildah run "$c" bash -x documentation/generator/build/main.sh "$BRANCH" "$PACKAGE_JOB" "$PACKAGE_UPLOAD_DIRECTORY" "$PACKAGE_BUILD" +buildah run "$c" bash -x documentation/generator/_scripts/_publish.sh "$BRANCH" diff --git a/generator/build/search/createIndex.js b/generator/build/search/createIndex.js index d6da646f5..e3e7263c2 100644 --- a/generator/build/search/createIndex.js +++ b/generator/build/search/createIndex.js @@ -2,7 +2,7 @@ const FlexSearch = require("flexsearch"); const fs = require('fs'); const {readdir} = require('fs').promises; -const htmlFilesDir = '../../_site'; +const htmlFilesDir = `${__dirname}/../../_site`; String.prototype.stripHtmlTags = function () { return this.replace(/<\/?[^>]+(>|$)/g, " "); @@ -63,7 +63,7 @@ const getHtmlFiles = async (dir) => breadCrumbs = breadCrumbsMatch[0].replace(/\s\s+/g, ' ').replace(/\n/g, " "); } - fs.writeFileSync(`searchIndex/documents/${key}.json`, JSON.stringify({ + fs.writeFileSync(`${__dirname}/searchIndex/documents/${key}.json`, JSON.stringify({ ...document, uri: (htmlFiles[key]), breadCrumbs @@ -71,5 +71,5 @@ const getHtmlFiles = async (dir) => index.add(document) } - index.export((key, data) => fs.writeFileSync(`searchIndex/${key}.json`, data || '')); + index.export((key, data) => fs.writeFileSync(`${__dirname}/searchIndex/${key}.json`, data || '')); })(); diff --git a/generator/package-lock.json b/generator/package-lock.json new file mode 100644 index 000000000..8efcb694f --- /dev/null +++ b/generator/package-lock.json @@ -0,0 +1,3241 @@ +{ + "name": "generator", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "less": "^4.2.0", + "less-loader": "^11.1.3", + "mini-css-extract-plugin": "^2.7.6", + "style-loader": "^3.3.3", + "terser-webpack-plugin": "^5.3.9", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/eslint": { + "version": "8.44.8", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz", + "integrity": "sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001568", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001568.tgz", + "integrity": "sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz", + "integrity": "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==", + "dev": true, + "dependencies": { + "cssnano-preset-default": "^6.0.1", + "lilconfig": "^2.1.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz", + "integrity": "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^4.0.0", + "postcss-calc": "^9.0.0", + "postcss-colormin": "^6.0.0", + "postcss-convert-values": "^6.0.0", + "postcss-discard-comments": "^6.0.0", + "postcss-discard-duplicates": "^6.0.0", + "postcss-discard-empty": "^6.0.0", + "postcss-discard-overridden": "^6.0.0", + "postcss-merge-longhand": "^6.0.0", + "postcss-merge-rules": "^6.0.1", + "postcss-minify-font-values": "^6.0.0", + "postcss-minify-gradients": "^6.0.0", + "postcss-minify-params": "^6.0.0", + "postcss-minify-selectors": "^6.0.0", + "postcss-normalize-charset": "^6.0.0", + "postcss-normalize-display-values": "^6.0.0", + "postcss-normalize-positions": "^6.0.0", + "postcss-normalize-repeat-style": "^6.0.0", + "postcss-normalize-string": "^6.0.0", + "postcss-normalize-timing-functions": "^6.0.0", + "postcss-normalize-unicode": "^6.0.0", + "postcss-normalize-url": "^6.0.0", + "postcss-normalize-whitespace": "^6.0.0", + "postcss-ordered-values": "^6.0.0", + "postcss-reduce-initial": "^6.0.0", + "postcss-reduce-transforms": "^6.0.0", + "postcss-svgo": "^6.0.0", + "postcss-unique-selectors": "^6.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz", + "integrity": "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.609", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.609.tgz", + "integrity": "sha512-ihiCP7PJmjoGNuLpl7TjNA8pCQWu09vGyjlPYw1Rqww4gvNuCcmvl+44G+2QyJ6S2K4o+wbTS++Xz0YN8Q9ERw==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/less": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.3.tgz", + "integrity": "sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw==", + "dev": true, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/needle": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.0.tgz", + "integrity": "sha512-Kaq820952NOrLY/LVbIhPZeXtCGDBAPVgT0BYnoT3p/Nr3nkGXdvWXXA3zgy7wpAgqRULu9p/NvKiFo6f/12fw==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz", + "integrity": "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz", + "integrity": "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz", + "integrity": "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz", + "integrity": "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz", + "integrity": "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz", + "integrity": "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz", + "integrity": "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz", + "integrity": "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz", + "integrity": "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz", + "integrity": "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==", + "dev": true, + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^4.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz", + "integrity": "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^4.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz", + "integrity": "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz", + "integrity": "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz", + "integrity": "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz", + "integrity": "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz", + "integrity": "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz", + "integrity": "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz", + "integrity": "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz", + "integrity": "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz", + "integrity": "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz", + "integrity": "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz", + "integrity": "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==", + "dev": true, + "dependencies": { + "cssnano-utils": "^4.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz", + "integrity": "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz", + "integrity": "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz", + "integrity": "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.0.2" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz", + "integrity": "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "optional": true + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", + "dev": true, + "optional": true + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylehacks": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz", + "integrity": "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svgo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.1.0.tgz", + "integrity": "sha512-R5SnNA89w1dYgNv570591F66v34b3eQShpIBcQtZtM5trJwm1VvxbIoMpRYY3ybTAutcKTLEmTsdnaknOHbiQA==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.2.1", + "css-what": "^6.1.0", + "csso": "5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", + "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack/node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/generator/package.json b/generator/package.json new file mode 100644 index 000000000..3774981fa --- /dev/null +++ b/generator/package.json @@ -0,0 +1,20 @@ +{ + "devDependencies": { + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "less": "^4.2.0", + "less-loader": "^11.1.3", + "mini-css-extract-plugin": "^2.7.6", + "style-loader": "^3.3.3", + "terser-webpack-plugin": "^5.3.9", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" + }, + "scripts": { + "searchIndex": "npm ci --prefix build/search && node build/search/createIndex.js", + "laodFonts": "npm ci --prefix _assets/styles", + "bundle": "node_modules/.bin/webpack-cli --config webpack.config.js --mode production", + "build": "npm ci && npm run searchIndex && npm run laodFonts && npm run bundle" + } +} diff --git a/generator/webpack.config.js b/generator/webpack.config.js new file mode 100644 index 000000000..309a3ea7e --- /dev/null +++ b/generator/webpack.config.js @@ -0,0 +1,49 @@ +const TerserPlugin = require("terser-webpack-plugin"); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const CopyPlugin = require("copy-webpack-plugin"); + +const jsFiles = [ + 'google_analytics_search.js', + 'jquery-1.9.1.min.js', + 'jquery-migrate-1.2.1.min.js', + 'jquery.sidr.min.js', + 'custom.js', + 'dropdown.js', +]; + +module.exports = { + entry: { + main: jsFiles.map(file => `${__dirname}/_assets/js/${file}`) + }, + output: { + filename: 'bundle.min.js', + path: __dirname + '/_site/assets', + }, + optimization: { + minimize: true, + minimizer: [new TerserPlugin(), new CssMinimizerPlugin()], + }, + module: { + rules: [ + { + test: /\.less$/i, + use: [ + MiniCssExtractPlugin.loader, + "css-loader", + "less-loader", + ], + }, + ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: 'styles.min.css' + }), + new CopyPlugin({ + patterns: [ + { from: `${__dirname}/build/search/searchIndex`, to: __dirname + '/_site/assets/searchIndex' } + ], + }), + ], +}; diff --git a/getting-started.markdown b/getting-started.markdown index eb3ff3bb9..bccbd8aae 100644 --- a/getting-started.markdown +++ b/getting-started.markdown @@ -1,6 +1,6 @@ --- layout: default -title: Getting Started +title: Getting started published: true sorting: 20 --- @@ -19,6 +19,6 @@ Afterwards, we will continue to more advanced topics, such as policy writing and 1. [Part 1: Installation][Installation] 2. [Part 2: Modules from CFEngine Build][Modules from CFEngine Build] -3. [Part 3: Reporting and Web UI][Reporting and Web UI] +3. [Part 3: Reporting and web UI][Reporting and web UI] 4. [Part 4: Writing policy][Writing policy] 5. [Part 5: Developing modules][Developing modules] diff --git a/getting-started/developing-modules.markdown b/getting-started/developing-modules.markdown index 50d608177..51c0c8cca 100644 --- a/getting-started/developing-modules.markdown +++ b/getting-started/developing-modules.markdown @@ -3,12 +3,11 @@ layout: default title: Developing modules published: true sorting: 50 -tags: [guide, getting started] --- Modules, such as the one we've used for git promises, are easy to write. In this tutorial, we will focus on implementing a new promise type in Python, with the provided CFEngine library, since this is the easiest and recommended way. -If you are interested in how modules are implemented, or how you could do it in another programming language, see the [complete documentation](/reference-promise-types-custom.html). +If you are interested in how modules are implemented, or how you could do it in another programming language, see the [complete documentation][custom]. In short, you need to implement 2 functions: `validate_promise()` and `evaluate_promise()`. _Validation_ should check that the correct attributes are used, and any other constraints you may want to enforce, to determine whether a promise is valid or invalid. @@ -27,7 +26,7 @@ https://github.com/cfengine/promise-type-template We can add it to our project with the full URL: -``` +```command cfbs add https://github.com/cfengine/promise-type-template ``` @@ -35,6 +34,7 @@ From that repo, we have now added a new promise type, it is called `git_example` Then, we should edit our policy example, `my_policy.cf` to use this module: ```cfengine3 +[file=my_policy.cf] bundle agent hello_world { meta: @@ -49,19 +49,19 @@ bundle agent hello_world That's it, you can now build and deploy: -``` +```command cfbs build && cf-remote deploy ``` And to test it, we can delete the folder and run the agent again: -``` +```command cf-remote sudo -H hub "rm -rf /tmp/hugo && cf-agent -KI | grep hugo" ``` The output printed from that remote machine shows that `cf-agent` cloned the repository again, after we deleted it: -``` +```output root@192.168.56.2: 'rm -rf /tmp/hugo && cf-agent -KI | grep hugo' -> ' info: Cloning 'https://github.com/gohugoio/hugo.git' -> '/tmp/hugo'...' root@192.168.56.2: ' info: Successfully cloned 'https://github.com/gohugoio/hugo.git' -> '/tmp/hugo'' ``` @@ -84,7 +84,7 @@ Start by editing `cfbs.json`, at least changing the `repo` and `by` URLs. To test your changes, make sure they are pushed to GitHub, and re-add your module, for example: -``` +```command cfbs remove promise-type-git-example && cfbs add https://github.com/cfengine/promise-type-template ``` @@ -92,13 +92,13 @@ cfbs remove promise-type-git-example && cfbs add https://github.com/cfengine/pro Then, build and deploy the project again: -``` +```command cfbs build && cf-remote deploy ``` And just like before, you can run manual agent runs to test: -``` +```command cf-remote sudo -H hub "rm -rf /tmp/hugo && cf-agent -KI" ``` @@ -107,15 +107,15 @@ cf-remote sudo -H hub "rm -rf /tmp/hugo && cf-agent -KI" As you've changed the high level things, like file name, promise type name, URLs, etc. and deployed that, the only thing you need to edit is the contents of the python file. So, to test your changes to the python file, a full build is not really necessary, you can just copy over that one file: -``` -cf-remote scp -H hub git_example.py /var/cfengine/masterfiles/modules/promises/git_example.py +```command +cf-remote scp -H hub git_example.py && cf-remote run -H hub "mv git_example.py /var/cfengine/masterfiles/modules/promises/git_example.py" ``` (Assuming you have the `git_example.py` file in the current directory). And then you can test it: -``` +```command cf-remote sudo -H hub "cf-agent -KIf update.cf && cf-agent -KI" ``` @@ -135,6 +135,6 @@ There are several places to look for more information or inspiration when writin * [The real git promise type code](https://github.com/cfengine/modules/tree/c3b7329b240cf7ad062a0a64ee8b607af2cb912a/promise-types/git/) * [HTTP promise type module](https://github.com/cfengine/modules/tree/c861789d4b376147d904fccd76963a92e65eaa97/promise-types/http/) -* [CFEngine custom promise type specification](/reference-promise-types-custom.html) +* [CFEngine custom promise type specification](./reference-promise-types-custom.html) * [Blog post: How to implement CFEngine Custom Promise Types in Python](https://cfengine.com/blog/2020/how-to-implement-cfengine-custom-promise-types-in-python/) * [Blog post: How to implement CFEngine Custom Promise Types in Bash](https://cfengine.com/blog/2021/how-to-implement-cfengine-custom-promise-types-in-bash/) diff --git a/getting-started/installation.markdown b/getting-started/installation.markdown index f9885b673..b9c3ca50a 100644 --- a/getting-started/installation.markdown +++ b/getting-started/installation.markdown @@ -3,7 +3,6 @@ layout: default title: Installation published: true sorting: 10 -tags: [guide, getting started, installation, modules] --- In CFEngine you mainly interact with the CFEngine Hub, for example using the Mission Portal Web UI, APIs, ssh, or git. @@ -49,7 +48,7 @@ Your **development machine** is the machine you have in front of you, it can be This is where you will run a terminal, browser, text editor, and some python tools. Throughout this tutorial we will tell you various commands to run on the command line (terminal), like this: -``` +```command echo hello ``` @@ -62,13 +61,13 @@ Feel free to use the copy to clipboard button and paste it into your terminal, o Install brew from [brew.sh](https://brew.sh/). Use brew to install Python 3: -``` +```command brew install python3 ``` **On Ubuntu:** -``` +```command sudo apt-get install python3 python3-pip ``` @@ -79,25 +78,19 @@ Not all systems use `apt-get` as the package manager - if you are not using Ubun To continue, you will need to be able to use `python3` and `pip3`: -``` +```command python3 --version ``` - -The output should look like this: - -``` +```output Python 3.10.8 ``` And similar for `pip`: -``` +```command pip3 --version ``` - -Output: - -``` +```output pip 22.3 from /usr/local/lib/python3.10/site-packages/pip (python 3.10) ``` @@ -111,13 +104,13 @@ These are small python tools and don't make changes to your system, they are onl Depending on your operating system and how you installed python, you may be able to install python tools without `sudo`. This is common on **macOS**: -``` +```command pip3 install cfbs cf-remote ``` However, on other systems, notably popular **Linux** distributions, it is common to require root privileges (or extra configuration) to install python packages: -``` +```command sudo pip3 install cfbs cf-remote ``` @@ -125,31 +118,28 @@ There are many ways to install command line tools with `pip`, if you want to do The commands above are suggestions which should work for most people. Importantly, you need the command line tools working after you've installed them: -``` +```command cfbs --version ``` Just as above, with python, you should see the version number like this: -``` +```output cfbs 3.1.1 ``` And similarly for `cf-remote`: -``` +```command cf-remote --version ``` - -Output: - -``` +```output cf-remote version 0.4.5 Available CFEngine versions: master, 3.20.0, 3.18.x, 3.18.2, 3.18.1, 3.18.0, 3.15.x, 3.15.6, 3.15.5, 3.15.4, 3.15.3, 3.15.2, 3.15.1, 3.15.0, 3.15.0b1 ``` -## Virtual Machine IP and username +## Virtual machine IP and username Decide on whether you want to use VMs in the cloud (Digital Ocean) or locally (Vagrant and Virtual Box) and follow the appropriate instructions below. @@ -175,7 +165,7 @@ Come back to this tutorial after you have completed the installation and setup o Test that ssh works: -``` +```command ssh root@192.168.56.2 -C "echo hello" ``` @@ -188,7 +178,7 @@ If you see `hello` printed, it worked! If not, these are some of the more common After you see ssh working, save the host in `cf-remote` so you can copy-paste our later commands: -``` +```command cf-remote save -H root@192.168.56.2 --role hub --name hub ``` @@ -196,13 +186,10 @@ cf-remote save -H root@192.168.56.2 --role hub --name hub The host is now in a `cf-remote` group called `hub`, so we don't have to type the username and IP, for example: -``` +```command cf-remote info -H hub ``` - -The output shows you the information needed for SSH (username and hostname / IP) as well as some key information about the host, such as architecture and operating system: - -``` +```output root@192.168.56.2 OS : Ubuntu 20 Architecture : x86_64 @@ -211,19 +198,21 @@ Policy server : None Binaries : dpkg, apt ``` +The output shows you the information needed for SSH (username and hostname / IP) as well as some key information about the host, such as architecture and operating system: + ## Install CFEngine From your development machine, use `cf-remote` to install CFEngine on the Linux VM: -``` +```command cf-remote install --hub hub --bootstrap hub ``` CFEngine is now installed and running on your hub, including the Web UI, the reporting database, and the components responsible for making changes to your system, serving and fetching policy, etc. -## Open the CFEngine Web UI +## Open the CFEngine web UI -Open the CFEngine Web UI in a web browser by clicking this link, or typing the appropriate IP in the address bar: +Open the CFEngine web UI in a web browser by clicking this link, or typing the appropriate IP in the address bar: https://192.168.56.2/ diff --git a/getting-started/installation/general-installation.markdown b/getting-started/installation/general-installation.markdown index 9b1b19f5b..81e90717b 100644 --- a/getting-started/installation/general-installation.markdown +++ b/getting-started/installation/general-installation.markdown @@ -1,18 +1,17 @@ --- layout: default -title: General Installation +title: General installation published: true sorting: 20 -tags: [guide, installation, install] --- [%CFEngine_include_markdown(include-install-bootstrap-configure-summary.markdown)%] -## Before Installation ## +## Before installation ## -Check the [Pre-Installation Checklist][Pre-Installation Checklist] and [Supported Platforms and Versions][Supported Platforms and Versions] for requirements and other information that is useful for the installation procedure. +Check the [Pre-installation checklist][Pre-installation checklist] and [Supported platforms and versions][Supported platforms and versions] for requirements and other information that is useful for the installation procedure. -## Install Packages ## +## Install packages ## CFEngine Enterprise is provided in two packages; one is for the Policy Server (hub) and the other is for each Host (client). @@ -24,15 +23,15 @@ Note: See [Installing Community][Installing Community] for the community version 1. On the designated Policy Server, install the `cfengine-nova-hub` package: ``` - [RedHat/CentOS/SUSE] $ rpm -i .rpm - [Debian/Ubuntu] $ dpkg -i .deb + [RedHat/CentOS/SUSE] # yum -y install /path/to/.rpm + [Debian/Ubuntu] # apt -y install /path/to/.deb ``` 2. On each Host, install the `cfengine-nova` package: ``` - [RedHat/CentOS/SUSE] $ rpm -i .rpm - [Debian/Ubuntu] $ dpkg -i .deb + [RedHat/CentOS/SUSE] # yum -y install /path/to/.rpm + [Debian/Ubuntu] # apt -y install /path/to/.deb ``` Note: Install actions logged to `/var/logs/cfengine-install.log`. @@ -49,18 +48,21 @@ Run the bootstrap command, **first** on the policy server: 1. Find the IP address of your Policy Server: - $ ifconfig +```command +ifconfig +``` 2. Run the bootstrap command: - - $ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +sudo /var/cfengine/bin/cf-agent --bootstrap +``` The bootstrap command must then be run on any client attaching itself to this server, using the ip address of the policy server (i.e. exactly the same as the command run on the policy server itself). -## Post-Installation Configuration ## +## Post-installation configuration ## CFEngine itself is configured through policy as well (see [Components][] and [Masterfiles Policy Framework][] for details). The following basic changes to the default policy will configure @@ -79,7 +81,9 @@ together. The preferred way of setting `def.mailfrom` is from the [augments file][Augments]. -``` +```json +[file=def.json] + { "vars": { "mailfrom": "sender@your.domain.here", @@ -103,7 +107,8 @@ ensure they have taken effect. The preferred way to disable the agent from sending emails is to define `cfengine_internal_disable_agent_email` from the [augments file][Augments]. -``` +```json +[file=def.json] { "classes": { "cfengine_internal_disable_agent_email": [ "any" ] @@ -116,26 +121,26 @@ Alternatively you can define the class from `def.cf`. **Note:** It's best practice to restart daemons after adjusting it's settings to ensure they have taken effect. -### Server IP Address and Hostname ### +### Server IP address and hostname ### Edit `/etc/hosts` and add an entry for the IP address and hostname of the server. -### CFEngine Enterprise Post-Installation Setup ### +### CFEngine Enterprise post-installation setup ### See: [What steps should I take after installing CFEngine Enterprise?][FAQ#What steps should I take after installing CFEngine Enterprise] -## More Detailed Installation Guides ## +## More detailed installation guides ## Although most install procedures follow the same general workflow, there are several ways of installing CFEngine depending on your environment and which version of CFEngine you are using. -* [Installing Enterprise for Production][Installing Enterprise for Production] +* [Installing Enterprise for production][Installing Enterprise for production] * Install and test the latest version using our [native version][Installing Enterprise 25 Free], for free! * Installing CFEngine on virtual machine instances using [Amazon Web Services' (AWS) EC2 service][Using Amazon Web Services] * This is especially useful for people running Windows on their workstation or laptop. * Install and test the latest version using our pre-packaged [Vagrant environment][Using Vagrant] * [Installing CFEngine Community Edition][Installing Community] -## Next Steps ## +## Next steps ## -* Learn about [Writing and Serving Policy][Writing and Serving Policy] +* Learn about [Writing and serving policy][Writing and serving policy] diff --git a/getting-started/installation/general-installation/common_next_steps.markdown b/getting-started/installation/general-installation/common_next_steps.markdown index d4bbc27c0..73c65b590 100644 --- a/getting-started/installation/general-installation/common_next_steps.markdown +++ b/getting-started/installation/general-installation/common_next_steps.markdown @@ -1,11 +1,11 @@ -# Next Steps +# Next steps -* [Writing and Serving Policy][Writing and Serving Policy] -* [Examples and Tutorials][Examples and Tutorials] -* ["Hello World" Tutorial][Examples and Tutorials#Tutorial for Running Examples] +* [Writing and serving policy][Writing and serving policy] +* [Examples and tutorials][Examples and tutorials] +* ["Hello World" Tutorial][Examples and tutorials#Tutorial for running examples] ## See also -* [General Installation][General Installation] -* [Post-Installation Configuration][General Installation#Post-Installation Configuration] +* [General installation][General installation] +* [Post-installation configuration][General installation#Post-installation configuration] * [FAQ][FAQ] diff --git a/getting-started/installation/general-installation/installation-community.markdown b/getting-started/installation/general-installation/installation-community.markdown index 83bc399a6..4b6460419 100644 --- a/getting-started/installation/general-installation/installation-community.markdown +++ b/getting-started/installation/general-installation/installation-community.markdown @@ -3,7 +3,6 @@ layout: default title: Installing Community published: true sorting: 50 -tags: [getting started, installation, community] --- These instructions describe how to download and install the latest version of CFEngine Community using pre-compiled rpm and @@ -11,36 +10,45 @@ deb packages for Ubuntu, Debian, Redhat, CentOS, and SUSE. It also provides instructions for the following: -* **Install CFEngine on a Policy Server (hub) and on a Host (client).** +* **Install CFEngine on a policy server (hub) and on a Host (client).** A Policy Server (hub) is a CFEngine instance that contains promises (business policy) that get deployed to Hosts. Hosts are clients that retrieve and execute promises. -* **Bootstrap the Policy Server to itself and then bootstrap the Host(s) to the Policy Server.** +* **Bootstrap the policy server to itself and then bootstrap the Host(s) to the Policy Server.** Bootstrapping establishes a trust relationship between the Policy Server and all Hosts. Thus, business policy that you create in the Policy Server can be deployed to Hosts throughout your company. Bootstrapping completes the installation process.
    -## Quick Setup Installation Script +## Quick setup with cf-remote -Please Note: Internet access is required from the host if you wish to use the quick install script. +`cf-remote` can be used to easily download, install, and bootstrap CFEngine on a host. -Use the following script to install CFEngine on your 32- or 64-bit machine. +Once `cf-remote` is installed from the Python Package Index (e.g. `pipx install cf-remote`), execute it against a host (either local or remote). -``` -$ wget -O- http://cfengine.package-repos.s3.amazonaws.com/quickinstall/quick-install-cfengine-community.sh | sudo bash -``` +For example, here we install CFEngine Community {{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}} on two hosts and bootstrap to one of them: -1. Run this script on your designated Policy Server machine **and** on your designated Host machine(s). -2. Bootstrap the Policy Server to itself and then bootstrap your Host(s) to the Policy Server by running the following command: -``` -$ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +cf-remote --version={{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}} install --edition community --clients 192.168.56.13,192.168.56.14 --bootstrap 192.168.56.13 ``` +## 1. Download packages + +Packages can be downloaded from the [community download page][community download page] or using `cf-remote`. -## 1. Download Packages +For example, this command downloads CFEngine 3.24.1 packages for ubuntu24 into the current directory: -Packages can be downloaded from the [community download page][community download page]. +```command +cf-remote --version 3.24.1 download ubuntu24 --edition community --output-dir . +``` +```output +Available releases: master, 3.25.0, 3.24.x, 3.24.1, 3.24.0, 3.21.x, 3.21.6, 3.21.5, 3.21.4, 3.21.3, 3.21.2, 3.21.1, 3.21.0 +Using 3.24.1 LTS: +Downloading package: '/home/user/.cfengine/cf-remote/packages/cfengine-community_3.24.1-1.ubuntu24_arm64.deb' +Copied to '/tmp/cfengine-community_3.24.1-1.ubuntu24_arm64.deb' (Checksum OK). +Downloading package: '/home/user/.cfengine/cf-remote/packages/cfengine-community_3.24.1-1.ubuntu24_amd64.deb' +Copied to '/tmp/cfengine-community_3.24.1-1.ubuntu24_amd64.deb' (Checksum OK). +``` -## 2. Install CFEngine on a Policy Server +## 2. Install CFEngine on a policy server Install the package on a machine designated as a Policy Server. A Policy Server is a CFEngine instance that contains promises (business policy) that get deployed to Hosts. Hosts are instances (clients) that retrieve and execute promises. @@ -49,52 +57,52 @@ Choose the right command for your operating system: **Newer 64-bit RPM based distributions: (Redhat/CentOS/SUSE)** -``` -$ sudo rpm -i cfengine-community-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.el6.x86_64.rpm +```command +sudo rpm -i cfengine-community-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.el6.x86_64.rpm ``` **Older 64-bit RPM based distributions: (Redhat/CentOS/SUSE)** (not recommended for policy server) -``` -$ sudo rpm -i cfengine-community-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.el4.x86_64.rpm +```command +sudo rpm -i cfengine-community-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.el4.x86_64.rpm ``` **32-bit RPM based distributions: (Redhat/CentOS/SUSE)** (not recommended for policy server) -``` -$ sudo rpm -i cfengine-community-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.el4.i386.rpm +```command +sudo rpm -i cfengine-community-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.el4.i386.rpm ``` **Newer 64-bit DEB based distributions: (Ubuntu/Debian)** -``` -$ sudo dpkg -i cfengine-community_{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}_amd64-debian7.deb` +```command +sudo dpkg -i cfengine-community_{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}_amd64-debian7.deb` ``` **Older 64-bit DEB based distributions: (Ubuntu/Debian)** (not recommended for policy server) -``` -$ sudo dpkg -i cfengine-community_{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}_amd64-debian4.deb` +```command +sudo dpkg -i cfengine-community_{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}_amd64-debian4.deb` ``` **32-bit DEB based distributions: (Ubuntu/Debian)** (not recommended for policy server) -``` -$ sudo dpkg -i cfengine-community_{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}_i386-debian4.deb` +```command +sudo dpkg -i cfengine-community_{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}_i386-debian4.deb` ``` **Note:** You might get a message like this: "Policy is not found in /var/cfengine/inputs, not starting CFEngine." Do not worry; this is taken care of during the bootstrapping process. -## 3. Bootstrap the Policy Server +## 3. Bootstrap the policy server The Policy Server must be bootstrapped to itself. Find the IP address of your Policy Server. Run the bootstrap command: -``` -$ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +sudo /var/cfengine/bin/cf-agent --bootstrap ``` **Example: $ sudo /var/cfengine/bin/cf-agent --bootstrap 192.168.1.12** @@ -103,25 +111,25 @@ Upon successful completion, a confirmation message appears: "Bootstrap to '192.1 Type the following to check which version of CFEngine your are running: -``` -$ /var/cfengine/bin/cf-promises --version +```command +/var/cfengine/bin/cf-promises --version ``` The Policy Server is installed. -## 4. Install CFEngine on a Host +## 4. Install CFEngine on a host As stated earlier, Hosts are instances that retrieve and execute promises from the Policy Server. Install a package on your Host. Use the same package you installed on the Policy Server in Step 2. Note that you must have access to at least one more VM or server and it must be on the same network as the Policy Server that you just installed. -## 5. Bootstrap the Host to the Policy Server +## 5. Bootstrap the host to the policy server The Host(s) must be bootstrapped to the Policy Server in order to establish a connection between the Host and the Policy Server. Run the same commands that you ran in Step 3. -``` -$ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +sudo /var/cfengine/bin/cf-agent --bootstrap ``` **Example: $ sudo /var/cfengine/bin/cf-agent --bootstrap 192.168.1.12** diff --git a/getting-started/installation/general-installation/installation-coreos.markdown b/getting-started/installation/general-installation/installation-coreos.markdown index 4d5148454..1b7e575c5 100644 --- a/getting-started/installation/general-installation/installation-coreos.markdown +++ b/getting-started/installation/general-installation/installation-coreos.markdown @@ -3,29 +3,28 @@ layout: default title: Installing Enterprise on CoreOS published: true sorting: 40 -tags: [getting started, installation, enterprise_edition, coreos] --- These instructions describe how to install the latest version of CFEngine Enterprise on CoreOS. The CoreOS package uses a file-system image in order to contain modifications to the root file-system. -## Download Packages +## Download packages Download the file-system image package for CoreOS from the [Enterprise Downloads Page](http://cfengine.com/product/free-download). -## Install Package +## Install package 1. On the CoreOS Host, extract the `fs-img-pkg.tar.gz` archive: - ```console - core@coreos ~ $ tar xvf cfengine-nova-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.x86_64.fs-img.pkg.tar.gz + ```command + tar xvf cfengine-nova-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.x86_64.fs-img.pkg.tar.gz ``` 2. On the CoreOS Host, run the install script: - ```console - core@coreos ~ $ sudo ./cfengine-nova-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.x86_64.fs-img.pkg/install.sh + ```command + sudo ./cfengine-nova-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.x86_64.fs-img.pkg/install.sh ``` Note: Install actions logged to `/var/log/CFEngine-Install.log`. @@ -34,11 +33,11 @@ Note: Install actions logged to `/var/log/CFEngine-Install.log`. Run the bootstrap command: -```console -core@coreos ~ $ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +sudo /var/cfengine/bin/cf-agent --bootstrap ``` -## Next Steps +## Next steps When bootstrapping is complete, CFEngine is up and running on your system. You can begin to manage the host through policy and report on its state from Mission diff --git a/getting-started/installation/general-installation/installation-enterprise-free-aws-rhel.markdown b/getting-started/installation/general-installation/installation-enterprise-free-aws-rhel.markdown index 435bf0cc1..e7516a3a1 100644 --- a/getting-started/installation/general-installation/installation-enterprise-free-aws-rhel.markdown +++ b/getting-started/installation/general-installation/installation-enterprise-free-aws-rhel.markdown @@ -3,7 +3,6 @@ layout: default title: Using Amazon Web Services published: true sorting: 10 -tags: [getting started, installation, enterprise free, aws, rhel] --- This guide describes how to install CFEngine on two Red Hat® Enterprise Linux® (RHEL) virtual machines using Amazon Web Services™ (AWS) and SSH. At the time of writing, under certain conditions, setting up an AWS account and using micro-instances is free. @@ -20,26 +19,26 @@ This tutorial will cover the following steps: 4. Configuring the Firewall on the Policy Server. 5. Installing CFEngine on both the Policy Server and Host Virtual Machines. -## Initial Configuration of the Virtual Machines in AWS ## +## Initial configuration of the virtual machines in AWS ## -### Configure 2 RHEL Virtual Machine Instances in AWS ### +### Configure 2 RHEL virtual machine instances in AWS ### * Login to AWS. * Under `Create Instance` click on `Launch Instance`. * On the line `Red Hat Enterprise Linux 64 Bit Free tier eligible` press the `Select` button. * On the `Choose Instance Type` screen ensure the `Micro Instances` tab on the left is selected. -### Configure Instance Details ### +### Configure instance details ### -* Press `Next: Configure Instance Details`. -* On the `Configure Instance Details` screen change the number of instances to 2. +* Press `Next: Configure instance details`. +* On the `Configure instance details` screen change the number of instances to 2. * Leave `Network` as the default. * `Subnet` can be `No preference`. * Ensure `Public IP` is checked. * Leave all else at their default values. -### Review and Launch ### -* Click `Review and Launch`. +### Review and launch ### +* Click `Review and launch`. * Make a note of `Security group` name on the `Review Instance Launch` screen. * Click `Launch`. * Select `Create a new key` pair in the first drop down menu. @@ -48,7 +47,7 @@ This tutorial will cover the following steps: * After the .pem file is saved click the `Launch Instance` button. * On the `Launch Status` screen click the `View Instances` button. -### Configure the Security Group ### +### Configure the security group ### * On the left hand side of the AWS console click `NETWORK & SECURITY > Security Groups` * Remembering the `Security group` name from earlier, click on the appropriate line item in the list. @@ -60,19 +59,19 @@ This tutorial will cover the following steps: * Copy the "Group ID" from the line containing your "Group Name" and copy the "Group ID" into the text entry in the last column. Click "Save." * Click the "Edit" button again. On the "Custom TCP" Rule, select "Anywhere" from the "Source" drop-down list. Click "Save." -## Accessing the Virtual Machines Using SSH ## +## Accessing the virtual machines using SSH ## See: [Quick-Start Guide to Using PuTTY][Quick-Start Guide to Using PuTTY] -## Install and Configure the Firewall ## +## Install and configure the firewall ## -### Install the Firewall ### +### Install the firewall ### * Ensure you are logged into both virtual machines. * In both enter `sudo yum install system-config-firewall` to install. * Hit 'y' if prompted. -### Configure the Firewall on the Policy Server (AKA hub) ### +### Configure the firewall on the policy server (AKA hub) ### The following steps are only necessary for one of the two virtual machines, the one that is designated as the policy server; these steps can be omitted on the second (client machine). Note that CFEngine refers to a client machine by the name `Host`: @@ -82,12 +81,12 @@ The following steps are only necessary for one of the two virtual machines, the ![The firewall Configuration window](Installing-CFE-on-AWS-8.png) -#### Open Port 80 (HTTPD) #### +#### Open port 80 (HTTPD) #### * On the `Trusted Services` screen, scroll down to `WWW (HTTP)`, AKA port 80. * Hit the `Space Bar` to toggle the `WWW` entry (i.e. ensure it is on, showing an asterisk beside the name). -#### Open Port 5308 (CFEngine) #### +#### Open port 5308 (CFEngine) #### * Hit the `Tab` key again until `Forward` is highlighted, then hit `Enter`. * Hit the `Tab` key until `Add` is highlighted, then hit `Enter`. @@ -101,12 +100,12 @@ The `Port and Protocol` are entered in the blue boxes, with entries of `5308` an Then the `Tab` key is used to highlight the `OK` button, and the user presses `Enter`. -#### Wrapping Up Firewall Configuration #### +#### Wrapping up firewall configuration #### * Hit the `Tab` key until `Close` is highlighted, and hit `Enter`. * Hit the `Tab` key or arrow keys until `OK` is highlighted, and hit `Enter`. -#### Disabling Firewall on a Host (Warning: Only Do This If Absolutely Necessary) #### +#### Disabling firewall on a host (Warning: Only do this if absolutely necessary) #### For the second virtual machine, which is the client machine (also called `host`), you may need to do the following if you see an error when bootstrapping this virtual machine in later steps: * In the `Firewall Configuration` screen use the `Tab` key to go to Firewall. @@ -114,27 +113,27 @@ For the second virtual machine, which is the client machine (also called `host`) Note: Turning off the firewall in a production environment is considered unsafe. -## CFEngine Installation Overview ## +## CFEngine installation overview ## We ready now ready to install the CFEngine software on both the server and client virtual machines. These also referred to as the "hub" and "host" machines, respectively. During the course of the instructions outlined in this guide, you will perform the following tasks: * Install CFEngine Enterprise onto a Policy Server and onto Hosts. A Policy Server (hub) is a CFEngine instance that contains promises (business policy) that get deployed to Hosts. Hosts are clients that retrieve and execute promises. -* Bootstrap the Policy Server to itself and then bootstrap each of the Hosts to the Policy Server. Bootstrapping establishes a trust relationship between the Policy Server and all Hosts. Thus, business policy that you create in the Policy Server can be deployed to Hosts throughout your company. Bootstrapping completes the installation process. +* Bootstrap the policy server to itself and then bootstrap each of the Hosts to the Policy Server. Bootstrapping establishes a trust relationship between the Policy Server and all Hosts. Thus, business policy that you create in the Policy Server can be deployed to Hosts throughout your company. Bootstrapping completes the installation process. * Log in to the Mission Portal. The Mission Portal is a graphical user interface that allows you to verify the actual state of all your Hosts, thus ensuring that your promises are being executed. * Try out the Tutorials. Links to three tutorials give you a head start on learning CFEngine. -### Step 1. Download and install Enterprise on a Policy Server ### +### Step 1. Download and install Enterprise on a policy server ### Run the following script on your designated Policy Server (hub), the virtual machine with the configured firewall from earlier steps: -```console -$ wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh hub +```command +wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh hub ``` This script installs the latest CFEngine Enterprise Policy Server on your server machine. -### Step 2. Bootstrap the Policy Server ### +### Step 2. Bootstrap the policy server ### * The Policy Server must be bootstrapped to itself. Find the IP address of your Policy Server: `$ ifconfig`. @@ -152,13 +151,13 @@ Upon successful completion, a confirmation message appears: "Bootstrap to '172.3 * The Policy Server is now installed. -### Step 3. Install Enterprise on Host (Client) ### +### Step 3. Install Enterprise on host (client) ### * Ensure you are logged into the host machine setup earlier. * Install CFEngine client version using the following: -```console -$ wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh agent +```command +wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh agent ``` Note: The installation will work on 64-bit and 32-bit client machines (the host requires a 64-bit machine). @@ -169,7 +168,7 @@ The client software (host), has been installed on the second virtual machine. Note: You can install CFEngine Enterprise on up to 25 hosts using the script above. -### Step 4. Bootstrap the Host to the Policy Server ### +### Step 4. Bootstrap the host to the policy server ### * All hosts must be bootstrapped to the Policy Server in order to establish a connection between the `Host` and the `Policy Server`. * Run the same commands that you ran in Step 2, `$ sudo /var/cfengine/bin/cfagent bootstrap `. @@ -185,17 +184,17 @@ Note: You can install CFEngine Enterprise on up to 25 hosts using the script abo * The Mission Portal runs TCP port 80 by default. [Configure mission portal to use HTTPS instead of HTTP](https://cfengine.zendesk.com/entries/25005193-Configure-Mission-Portal-to-use-HTTPS-instead-of-HTTP). * During the initial setup, the Host(s) might take a few minutes to show up in the Mission Portal. Refresh the web page and login again if necessary. -## What Next? ## +## What next? ## ### Tutorials ### -* [Tutorial for Running Examples][Examples and Tutorials#Tutorial for Running Examples] +* [Tutorial for running examples][Examples and tutorials#Tutorial for running examples] -* [Distribute files from a central location.][Distribute files from a central location] +* [Distributing files from a central location.][Distributing files from a central location] Whereas the first tutorial in this list teaches you how to deploy business policy through the Mission Portal, this advanced, command-line tutorial shows you how to distribute policy files from the Policy Server to all pertinent Hosts. -### Recommended Reading ### +### Recommended reading ### -* [Tutorials and Examples][Examples and Tutorials] +* [Tutorials and Examples][Examples and tutorials] diff --git a/getting-started/installation/general-installation/installation-enterprise-free.markdown b/getting-started/installation/general-installation/installation-enterprise-free.markdown index 43cff053f..209408dba 100644 --- a/getting-started/installation/general-installation/installation-enterprise-free.markdown +++ b/getting-started/installation/general-installation/installation-enterprise-free.markdown @@ -3,7 +3,6 @@ layout: default title: Installing Enterprise 25 Free published: true sorting: 20 -tags: [getting started, installation, enterprise free] --- These instructions describe how to install the latest version of CFEngine Enterprise 25 Free. This is the full @@ -27,7 +26,7 @@ During the course of the instructions outlined in this guide, you will perform t * **Install CFEngine Enterprise onto a Policy Server and onto Hosts.** A Policy Server (hub) is a CFEngine instance that contains promises (business policy) that get deployed to Hosts. Hosts are clients that retrieve and execute promises. -* **Bootstrap the Policy Server to itself and then bootstrap each of the Hosts to the Policy Server.** Bootstrapping establishes a trust relationship between the Policy Server +* **Bootstrap the policy server to itself and then bootstrap each of the Hosts to the Policy Server.** Bootstrapping establishes a trust relationship between the Policy Server and all Hosts. Thus, business policy that you create in the Policy Server can be deployed to Hosts throughout your company. Bootstrapping completes the installation process. * **Log in to the Mission Portal.** The Mission Portal is a graphical user interface that allows you to verify the @@ -35,26 +34,26 @@ the actual state of all your Hosts, thus ensuring that your promises are being e * **Try out the Tutorials.** Links to three tutorials give you a head start on learning CFEngine. -## 1. Download and install Enterprise on a Policy Server +## 1. Download and install Enterprise on a policy server Please Note: Internet access is required from the host if you wish to use the quick install script. Run the following script on your designated Policy Server (hub) 64-bit machine (32-bit is not supported on the Policy Server): -```console -$ wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh hub +```command +wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh hub ``` This script installs the latest CFEngine Enterprise Policy Server on your machine. -## 2. Bootstrap the Policy Server +## 2. Bootstrap the policy server The Policy Server must be bootstrapped to itself. Find the IP address of your Policy Server (type $ ifconfig). Run the bootstrap command: -```console -$ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +sudo /var/cfengine/bin/cf-agent --bootstrap ``` **Example: $ sudo /var/cfengine/bin/cf-agent --bootstrap 192.168.1.12** @@ -63,8 +62,8 @@ Upon successful completion, a confirmation message appears: "Bootstrap to '192.1 Type the following to check which version of CFEngine your are running: -```console -$ /var/cfengine/bin/cf-promises --version +```command +/var/cfengine/bin/cf-promises --version ``` The Policy Server is installed. @@ -75,19 +74,19 @@ Install Enterprise on your designated Host(s) by running the script below. Per t install Enterprise on 25 Hosts. Note that the Hosts must be on the same network as the Policy Server that you just installed in Step 2. -```console -$ wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh agent +```command +wget https://s3.amazonaws.com/cfengine.packages/quick-install-cfengine-enterprise.sh && sudo bash ./quick-install-cfengine-enterprise.sh agent ``` Note that this installation works on 64- and 32-bit machines. -## 4. Bootstrap the Host to the Policy Server +## 4. Bootstrap the host to the policy server All Hosts must be bootstrapped to the Policy Server in order to establish a connection between the Host and the Policy Server. Run the same commands that you ran in Step 3. -```console -$ sudo /var/cfengine/bin/cf-agent --bootstrap +```command +sudo /var/cfengine/bin/cf-agent --bootstrap ``` **Example: $ sudo /var/cfengine/bin/cf-agent --bootstrap 192.168.1.12** @@ -116,13 +115,13 @@ number you use in your **Vagrantfile** (e.g. policyserver.vm.network "forwarded_ ## Tutorials -* [Tutorial for Running Examples][Examples and Tutorials#Tutorial for Running Examples] +* [Tutorial for running examples][Examples and tutorials#Tutorial for running examples] -* [Distribute files from a central location.][Distribute files from a central location] +* [Distributing files from a central location.][Distributing files from a central location] Whereas the first tutorial in this list teaches you how to deploy business policy through the Mission Portal, this advanced, command-line tutorial shows you how to distribute policy files from the Policy Server to all pertinent Hosts. -## Recommended Reading +## Recommended reading -* [Tutorials and Examples][Examples and Tutorials] +* [Tutorials and Examples][Examples and tutorials] diff --git a/getting-started/installation/general-installation/installation-enterprise-generic-tarball.markdown b/getting-started/installation/general-installation/installation-enterprise-generic-tarball.markdown index ad2b5a19a..f17b3b13a 100644 --- a/getting-started/installation/general-installation/installation-enterprise-generic-tarball.markdown +++ b/getting-started/installation/general-installation/installation-enterprise-generic-tarball.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Installing from Binary tarball +title: Installing from binary tarball published: true sorting: 50 -tags: [getting started, installation] --- Not all systems come with a package manager. For these systems you can install @@ -13,19 +12,19 @@ First download the binary onto the host. Next unpack the archive. For the 64 bit tarball use: -```sh +```command tar --gunzip --extract --directory / --file ./cfengine-nova-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.x86_64.pkg.tar.gz ``` Otherwise, for 32 bit tarball, use: -```sh +```command tar --gunzip --extract --directory / --file ./cfengine-nova-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.i386.pkg.tar.gz ``` Generate a keypair for the client: -```sh +```command /var/cfengine/bin/cf-key ``` diff --git a/getting-started/installation/general-installation/installation-enterprise-vagrant.markdown b/getting-started/installation/general-installation/installation-enterprise-vagrant.markdown index bfa3cc00d..071bb2074 100644 --- a/getting-started/installation/general-installation/installation-enterprise-vagrant.markdown +++ b/getting-started/installation/general-installation/installation-enterprise-vagrant.markdown @@ -3,7 +3,6 @@ layout: default title: Using Vagrant published: true sorting: 30 -tags: [getting started, installation, enterprise, vagrant] --- The CFEngine Enterprise Vagrant Environment provides an easy way to test and @@ -11,7 +10,7 @@ explore CFEngine Enterprise. This guide describes how to set up a client-server model with CFEngine and, through policy, manage both machines. Vagrant will create one VirtualBox VM to be the Policy Server (server), and another machine that will be the Host Agent (client), or host that can be managed by CFEngine. -Both will will run CentOS 6.5 64-bit and communicate on a host-only network. +Both running 64-bit Debian and communicate on a host-only network. Apart from a one-time download of Vagrant and VirtualBox, this setup requires just one command and takes between 5 and 15 minutes to complete (determined by your Internet connection and disk speed). Upon completion, you are ready to @@ -19,17 +18,17 @@ start working with CFEngine. ## Requirements * 2G disk space -* 1G memory +* 3G memory * CPU with VT extensions capable of running 64bit guests Note: VirtualBox requires that your computer support hardware virtualization -in order to make use of the CentOS 64-bit virtual machines mentioned above. +in order to make use of the virtual machines mentioned above. This is sometimes turned on or off in BIOS settings, but not all processors and motherboards necessarily support hardware virtualization. If your system lacks this support you will need to choose another computer to take advantage of the 64-bit virtual machines or [install CFEngine using a -different approach][General Installation#More Detailed Installation Guides]. +different approach][General installation#More detailed installation guides]. ## Overview @@ -56,7 +55,7 @@ virtualbox.org. After downloading VirtualBox, install it on your computer. **Note:** To avoid problems, disable other virtualization environments you are running. -## Start the CFEngine Enterprise {{site.cfengine.branch}} Vagrant Environment +## Start the CFEngine Enterprise {{site.cfengine.branch}} Vagrant environment Step 1. Download our ready-made Vagrant project [tar-file](https://cfengine-package-repos.s3.amazonaws.com/enterprise/Enterprise-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}/misc/CFEngine_Enterprise_vagrant_quickstart-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}.tar.gz). @@ -67,13 +66,13 @@ creates a Vagrant Project directory. Step 3. Open a terminal and navigate to the Vagrant Project directory (e.g. `/home/user/CFEngine_Enterprise_vagrant_quickstart-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}`, or `C:\CFEngine_Enterprise_vagrant_quickstart-{{site.cfengine.branch}}.{{site.cfengine.latest_patch_release}}-{{site.cfengine.latest_package_build}}`) and enter the following command: -```console -$ vagrant up +```command +vagrant up ``` Vagrant performs the following processes: -* Downloads the CentOS basebox used for both the hub and the client (if it has +* Downloads the basebox for both the hub and the client (if it has not already been cached by vagrant. * Provisions, installs and bootstraps the hub * Provisions, installs and bootstraps clients @@ -100,7 +99,7 @@ password: admin Portal. That's all there is to it, the install is complete! Move on and explore the environment. -## Exploring the Environment +## Exploring the environment ### Accessing VMs @@ -113,8 +112,10 @@ status` output. Both the 'root' and 'vagrant' users passwords are set to **Example:** -```console -$ vagrant ssh hub +```command +vagrant ssh hub +``` +```output Last login: Fri Jun 13 18:58:10 2014 from 10.0.2.2 ``` @@ -131,8 +132,10 @@ for the clients. Running `vagrant status` from the vagrant project directroy will produce output like this. -```console -$ vagrant status +```command +vagrant status +``` +```output Current machine states: hub not created (virtualbox) @@ -148,17 +151,19 @@ VM, run `vagrant status NAME`. To start or resume a halted environment simply run `vagrant up` from within the vagrant project directory. -```console -$ vagrant up +```command +vagrant up ``` -### Stop the environment (Halt/Suspend/Destroy) +### Stop the environment (halt/suspend/destroy) To shut down the vms run `vagrant halt`. This will preserve the vms and any changes made inside. -```console -$ vagrant suspend +```command +vagrant suspend +``` +```output ==> hub: Saving VM state and suspending execution... ==> host001: Saving VM state and suspending execution... ``` @@ -166,8 +171,10 @@ $ vagrant suspend To suspend the vms run `vagrant suspend`. This will freeze the state of each vm and allows for latter resuming of the environment. -```console -$ vagrant halt +```command +vagrant halt +``` +```output ==> host001: Attempting graceful shutdown of VM... ==> hub: Attempting graceful shutdown of VM... ``` @@ -175,8 +182,10 @@ $ vagrant halt At any time you can run `vagrant destroy` to remove the provisioned vms. This will delete the vms and any modifications made to the environment will be lost. -```console -$ vagrant destroy +```command +vagrant destroy +``` +```output host001: Are you sure you want to destroy the 'host001' VM? [y/N] y ==> host001: Forcing shutdown of VM... ==> host001: Destroying VM and associated drives... @@ -191,7 +200,7 @@ $ vagrant destroy ==> hub: Running cleanup tasks for 'shell' provisioner... ``` -## Uninstall Vagrant Environment +## Uninstall Vagrant environment When you have completed your evaluation are ready to use CFEngine on production servers, remove the VMs that you created above by following these @@ -200,9 +209,9 @@ simple instructions: To remove the VMs entirely, type: `vagrant destroy` If you are completely done and do not anticipate using them anymore, you can -also remove the base box `centos-6.5-x86_64-cfengine_enterprise-vagrant-201501201245` that was +also remove the base box that was downloaded. You can see it by typing `vagrant box list`. To delete the basebox -run `vagrant box remove centos-6.5-x86_64-cfengine_enterprise-vagrant-201501201245 virtualbox`. +run `vagrant box remove virtualbox`. **Note:** Running `vagrant up` from the vagrant project directory again will re-download this basebox. diff --git a/getting-started/installation/general-installation/installation-enterprise.markdown b/getting-started/installation/general-installation/installation-enterprise.markdown index 753ca8735..a123d1091 100644 --- a/getting-started/installation/general-installation/installation-enterprise.markdown +++ b/getting-started/installation/general-installation/installation-enterprise.markdown @@ -1,16 +1,15 @@ --- layout: default -title: Installing Enterprise for Production +title: Installing Enterprise for production published: true sorting: 40 -tags: [getting started, installation, enterprise production] --- These instructions describe how to install the latest version of CFEngine Enterprise in a production environment using pre-compiled rpm and deb packages for Ubuntu, Debian, Redhat, CentOS, and SUSE. -## General Requirements +## General requirements CFEngine recommends the following: @@ -70,7 +69,7 @@ resource utilization may vary depending on the policy CFEngine is running. The VIOS should be configured with Shared Processors in Uncapped mode. -## Policy Server Requirements +## Policy server requirements Please note that the resource requirements below are meant as minimum guidelines and have been obtained with synthetic testing, and it is @@ -183,15 +182,15 @@ hard nofile 4000 Not sure what your open file limits for `cf-serverd` are? Inspect the current limits with this command: -``` +```command cat /proc/$(pgrep cf-serverd)/limits ``` -## Download Packages +## Download packages [Download CFEngine](http://cfengine.com/product/free-download) -## Install Packages +## Install packages CFEngine Enterprise is provided in two packages; one is for the Policy Server (hub) and the other is for each Host (client). @@ -203,15 +202,15 @@ Server (hub) and the other is for each Host (client). 1. On the designated Policy Server, install the `cfengine-nova-hub` package: ```console - [RedHat/CentOS/SUSE] # rpm -i .rpm - [Debian/Ubuntu] # dpkg -i .deb + [RedHat/CentOS/SUSE] # yum -y install /path/to/.rpm + [Debian/Ubuntu] # apt -y install /path/to/.deb ``` 2. On each Host, install the `cfengine-nova` package: ```console - [RedHat/CentOS/SUSE] # rpm -i .rpm - [Debian/Ubuntu] # dpkg -i .deb + [RedHat/CentOS/SUSE] # yum -y install /path/to/.rpm + [Debian/Ubuntu] # apt -y install /path/to/.deb [Solaris] # pkgadd -d .pkg all [AIX] # installp -a -d .bff cfengine.cfengine-nova [HP-UX] # swinstall -s .depot cfengine-nova @@ -224,14 +223,14 @@ Note: Install actions logged to `/var/logs/cfengine-install.log`. Run the bootstrap command, **first** on the policy server and then on each host: -```console -# /var/cfengine/bin/cf-agent --bootstrap +```command +/var/cfengine/bin/cf-agent --bootstrap ``` After bootstrapping the hub run the policy to complete the hub configuration. -```console -# /var/cfengine/bin/cf-agent -Kf update.cf; /var/cfengine/bin/cf-agent -K +```command +/var/cfengine/bin/cf-agent -Kf update.cf; /var/cfengine/bin/cf-agent -K ``` ## Licensed installations @@ -246,18 +245,18 @@ to CFEngine support to obtain a license. It's best to pack the public key into an archive so that it does not get corrupt in transit. -```console -# tar --create --gzip --directory /var/cfengine --file $(hostname)-ppkeys.tar.gz ppkeys/localhost.pub +```command +tar --create --gzip --directory /var/cfengine --file $(hostname)-ppkeys.tar.gz ppkeys/localhost.pub ``` CFEngine will send you a `license.dat` file. Install the obtained license with `cf-key`. -```console -# cf-key --install-license ./license.dat +```command +cf-key --install-license ./license.dat ``` -## Next Steps +## Next steps When bootstrapping is complete, CFEngine is up and running on your system. @@ -266,6 +265,6 @@ through your web browser at http://``. Learn more about CFEngine by using the following resources: -* Tutorial: [Tutorial for Running Examples][Examples and Tutorials#Tutorial for Running Examples] +* Tutorial: [Tutorial for running examples][Examples and tutorials#Tutorial for running examples] -* [Tutorials and Examples][Examples and Tutorials] +* [Tutorials and Examples][Examples and tutorials] diff --git a/getting-started/installation/installation-overview.markdown b/getting-started/installation/installation-overview.markdown index 97c5a862b..8ea51882d 100644 --- a/getting-started/installation/installation-overview.markdown +++ b/getting-started/installation/installation-overview.markdown @@ -3,27 +3,26 @@ layout: default title: Installation overview sorting: 30 published: true -tags: [getting started, installation] --- ## Installation ## [%CFEngine_include_markdown(include-install-bootstrap-configure-summary.markdown)%] -See [General Installation][General Installation] for a more detailed guide for how to install CFEngine, and links to installation guides for various versions of CFEngine and different configurations. +See [General installation][General installation] for a more detailed guide for how to install CFEngine, and links to installation guides for various versions of CFEngine and different configurations. -See [Secure Bootstrap] for a guide on bootstrapping CFEngine in untrusted networks. +See [Secure bootstrap] for a guide on bootstrapping CFEngine in untrusted networks. -See also: [Pre-Installation Checklist][Pre-Installation Checklist], [Supported Platforms and Versions][Supported Platforms and Versions] +See also: [Pre-installation checklist][Pre-installation checklist], [Supported platforms and versions][Supported platforms and versions] -## Setup & Configuration ## +## Setup & configuration ## Additional options for configuring CFEngine policy are as follows: -* [Controlling Frequency] +* [Controlling frequency] Learn how to control frequency settings for verifying CFEngine policy. -* [Version Control] +* [Version control] Learn how to put your CFEngine policies under version control. * [Masterfiles Policy Framework] diff --git a/getting-started/installation/local-virtual-machine.markdown b/getting-started/installation/local-virtual-machine.markdown index 0d41f5f3e..384eb42e2 100644 --- a/getting-started/installation/local-virtual-machine.markdown +++ b/getting-started/installation/local-virtual-machine.markdown @@ -3,7 +3,6 @@ layout: default title: Local virtual machine published: true sorting: 15 -tags: [guide, getting started, installation, modules] --- This short tutorial shows you how to set up a Linux Virtual Machine locally, if you prefer this over creating an account and using an online cloud provider like Digital Ocean. @@ -29,20 +28,20 @@ VirtualBox is used for virtualization, and vagrant is a nice way of interacting If you've never used SSH before, you need to generate a new SSH key: -``` +```command ssh-keygen ``` You can use the defaults, just press enter instead of typing things. After running the commands or if you already have been using SSH, you should be able to find your public key: -``` +```command ls ~/.ssh/ ``` The output should look like this: -``` +```output id_rsa id_rsa.pub known_hosts ``` @@ -54,13 +53,13 @@ id_rsa id_rsa.pub known_hosts We need a project folder where we will place the file(s) needed for both vagrant and later CFEngine: -``` +```command mkdir -p ~/cfengine_project && cd ~/cfengine_project ``` Now, inside the folder, we can create and edit the `Vagrantfile`: -``` +```command touch Vagrantfile && code Vagrantfile ``` @@ -69,6 +68,7 @@ touch Vagrantfile && code Vagrantfile Put this in your `Vagrantfile`: ```ruby +[file=Vagrantfile] # -*- mode: ruby -*- # vi: set ft=ruby : @@ -107,11 +107,11 @@ The `Vagrantfile` above does some important things: **Note:** The machine will be called `hub` in `vagrant`, `cf-remote` and in Mission Portal (based on hostname), but this is just because we were consistent when naming it in all 3 places. These 3 names do not have to match, but it is easier to remember -## Start the Virtual Machine +## Start the virtual machine To start our VM, make sure you've saved the file above, with the filename `Vagrantfile` and run this command in the same folder: -``` +```command vagrant up hub ``` @@ -119,11 +119,11 @@ At this point, the VM should work like any Linux VM, similar to if you spawned i **Note:** Later, when you are done working with the Virtual Machine and want to get rid of it, run the following command: -``` +```command vagrant destroy hub ``` -## Back to CFEngine Installation +## Back to CFEngine installation Now that you have a Linux VM ready, go back to the main tutorial to install CFEngine: diff --git a/getting-started/installation/pre-installation-checklist.markdown b/getting-started/installation/pre-installation-checklist.markdown index 5f8e7f1bb..d07a0f3f0 100644 --- a/getting-started/installation/pre-installation-checklist.markdown +++ b/getting-started/installation/pre-installation-checklist.markdown @@ -1,19 +1,18 @@ --- layout: default -title: Pre-Installation Checklist +title: Pre-installation checklist published: true sorting: 10 -tags: [guide, installation] --- -## Download Packages +## Download packages [Download CFEngine][enterprise software download page] packages and [verify their signatures][Verifying package signatures]. ## System requirements -Please see [Installing Enterprise for Production][Installing Enterprise for Production] for hardware and configuration requirements, and -for [Supported Platforms and Versions][Supported Platforms and Versions] operating system support. +Please see [Installing Enterprise for production][Installing Enterprise for production] for hardware and configuration requirements, and +for [Supported platforms and versions][Supported platforms and versions] operating system support. ## Required knowledge @@ -22,4 +21,4 @@ for [Supported Platforms and Versions][Supported Platforms and Versions] operati * bash * command line text editing (e.g. vi/vim, Emacs) -See Also: [Quick-Start Guide to Using vi][Quick-Start Guide to Using vi], [Quick-Start Guide to Using PuTTY][Quick-Start Guide to Using PuTTY] +See also: [Quick-Start Guide to Using vi][Quick-Start Guide to Using vi], [Quick-Start Guide to Using PuTTY][Quick-Start Guide to Using PuTTY] diff --git a/getting-started/installation/pre-installation-checklist/putty-quick-start-guide.markdown b/getting-started/installation/pre-installation-checklist/putty-quick-start-guide.markdown index d43b21ef2..2e1f8b260 100644 --- a/getting-started/installation/pre-installation-checklist/putty-quick-start-guide.markdown +++ b/getting-started/installation/pre-installation-checklist/putty-quick-start-guide.markdown @@ -1,15 +1,14 @@ --- -title: Quick-Start Guide to Using PuTTY +title: Quick-Start guide to using PuTTY layout: default published: true sorting: 2 -tags: [how-to-guides, quick-start guides, putty, puttygen] --- -* [Using PuTTY in Simple Steps][Quick-Start Guide to Using PuTTY#Using PuTTY in Simple Steps] -* [Accessing AWS Virtual Machines via SSH on Windows Using PuTTY and PuTTYgen][Quick-Start Guide to Using PuTTY#Accessing AWS Virtual Machines via SSH on Windows Using PuTTY and PuTTYgen] +* [Using PuTTY in simple steps][Quick-Start Guide to Using PuTTY#Using PuTTY in simple steps] +* [Accessing AWS virtual machines via SSH on Windows using PuTTY and PuTTYgen][Quick-Start Guide to Using PuTTY#Accessing AWS virtual machines via SSH on Windows using PuTTY and PuTTYgen] -## Using PuTTY in Simple Steps ## +## Using PuTTY in simple steps ## This guide is intended for Windows users who are not accustomed to using SSH, or need some additional support for understanding how to work with SSH from their machine (e.g. challenges with key pairs). @@ -23,15 +22,15 @@ using the SSH network protocol. It has a powerful and easy-to-use graphical use to run a remote session over a network. What is SSH? It is short-form for "Secure Shell," which means it creates a _secure channel_ over an -insecure network—like the internet, for example. +insecure network-like the internet, for example. How does SSH do this? By encrypting the communications between the client and the server, using -public-key cryptography, which means that a key-pair is generated—one of them public, and the other +public-key cryptography, which means that a key-pair is generated-one of them public, and the other private, or secret, known only to the user. Since CFEngine is a client-server enterprise software system, it is essential to access the servers securely. This is true whether the CFEngine system is run on a cloud platform, like Amazon Web Services -and many others—or on a private network. +and many others-or on a private network. That is where PuTTY comes into the picture, since it uses SSH protocol for connecting a client to a server. @@ -83,7 +82,7 @@ f. If saving without a _Passphrase_ a dialog box will pop up; click _yes_ to sav g. Now close PuTTYgen. -## Accessing AWS Virtual Machines via SSH on Windows Using PuTTY and PuTTYgen ## +## Accessing AWS virtual machines via SSH on Windows using PuTTY and PuTTYgen ## ### Get PuTTY and PuTTYgen ### @@ -92,7 +91,7 @@ http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html and either: * Download and install using the PuTTY binaries installer * Or, download PuTTY and PuTTYgen individually -### Prepare Private Key Using PuTTYgen ### +### Prepare private key using PuTTYgen ### * After the binaries have been downloaded and/or installed either: * Double click `puttygen.exe` from the download location, if downloaded directly. * Or, if the PuTTY installer was used above, one of either: @@ -163,7 +162,7 @@ Note that `Auth` has been selected on left-side tree, in order to bring up this The PuTTY interface with the two virtual machines saved. We can now proceed to configure those virtual machines with CFEngine. -### Login to Virtual Machines Using PuTTY ### +### Login to virtual machines using PuTTY ### * If one of the two virtual machines is configured and its details loaded in the PuTTY interface, first select the machine, then click the Open button. This will close the above PuTTY interface and open a command-line window, from which we will setup CFEngine on each of the two machines. One machine will act as the Server and the other as the client, and they will each be set up with different software. * Once the first virtual machine is logged into, right click the top of PuTTY's application window (e.g. the part of the window decoration displaying the virtual machine name). diff --git a/getting-started/installation/pre-installation-checklist/verify-signatures.markdown b/getting-started/installation/pre-installation-checklist/verify-signatures.markdown index 867ed337b..f143cc360 100644 --- a/getting-started/installation/pre-installation-checklist/verify-signatures.markdown +++ b/getting-started/installation/pre-installation-checklist/verify-signatures.markdown @@ -3,7 +3,6 @@ layout: default title: Verifying package signatures published: true sorting: 40 -tags: [getting started, installation] --- On the [Download CFEngine][enterprise software download page], you will find @@ -20,21 +19,25 @@ NOTE: AIX rpms currently are NOT signed because it's not supported on older vers 1. Import the public GPG key. -```console -# rpm --import https://cfengine-package-repos.s3.amazonaws.com/pub/gpg.key +```command +rpm --import https://cfengine-package-repos.s3.amazonaws.com/pub/gpg.key ``` 2. Validate the signature. -```console -# rpm -K ./cfengine-nova-hub-3.12.2-2.x86_64.rpm +```command +rpm -K ./cfengine-nova-hub-3.12.2-2.x86_64.rpm +``` +```output ./cfengine-nova-hub-3.12.2-2.x86_64.rpm: rsa sha1 (md5) pgp md5 OK ``` NOTE: If you don't import the public key first, you will get an error about the key missing: -```console -# rpm -K ./cfengine-nova-hub-3.12.2-2.x86_64.rpm +```command +rpm -K ./cfengine-nova-hub-3.12.2-2.x86_64.rpm +``` +```output ./cfengine-nova-hub-3.12.2-2.x86_64.rpm: RSA sha1 ((MD5) PGP) md5 NOT OK (MISSING KEYS: (MD5) PGP#a86e7afa) ``` @@ -69,7 +72,9 @@ NOTE: If you don't import the public key first, you will get an error about the 3. Validate the signature. -```console -# debsig-verify cfengine-nova-hub_3.12.2-2_amd64.deb +```command +debsig-verify cfengine-nova-hub_3.12.2-2_amd64.deb +``` +```output debsig: Verified package from 'CFEngine 3' (cfengine3) ``` diff --git a/getting-started/installation/pre-installation-checklist/vi-quick-start-guide.markdown b/getting-started/installation/pre-installation-checklist/vi-quick-start-guide.markdown index 49ae20c7b..fefccee6b 100644 --- a/getting-started/installation/pre-installation-checklist/vi-quick-start-guide.markdown +++ b/getting-started/installation/pre-installation-checklist/vi-quick-start-guide.markdown @@ -1,27 +1,26 @@ --- layout: default -title: Quick-Start Guide to Using vi +title: Quick-Start guide to using vi published: true sorting: 1 -tags: [how-to-guides, quick-start guides, vi] --- -This guide is designed for the novice user of CFEngine tutorials—and will introduce the basic +This guide is designed for the novice user of CFEngine tutorials-and will introduce the basic use of a powerful tool that is referenced in the CFEngine learning documentation: the vi visual editor. -What is a visual editor? It lets you see multiple lines of the document you are editing—rather than +What is a visual editor? It lets you see multiple lines of the document you are editing-rather than simply issuing commands in the shell prompt. This means you can insert a very large piece of text and navigate anywhere in that text, and make changes. -The vi editor was developed for unix—but can run from any shell prompt, like PuTTY on the Windows platform, +The vi editor was developed for unix-but can run from any shell prompt, like PuTTY on the Windows platform, and also the Mac. So whatever the user's platform may be, learning to use vi will be very useful in working through the CFEngine tutorials. When working in the CFEngine tutorials, vi will be used to do things like open files, insert text, save files, and many other functions. -vi will also be used when the CFEngine user starts to actually use the CFEngine software—for things +vi will also be used when the CFEngine user starts to actually use the CFEngine software-for things like writing and deploying promises, the core of the CFEngine technology. Learning the basics of vi is quite simple. The best way is by walking through an example. @@ -30,12 +29,12 @@ Step 1. Inside the shell prompt, simply type "vi". This will allow the user to i Step 2. type "i" then press the "Enter" key. This takes the user to the insert mode, and allow typing in text or copying and pasting. -Step 3. Type some text—for example, the obligatory "Hello World" (which will be the subject of a later tutorial). +Step 3. Type some text-for example, the obligatory "Hello World" (which will be the subject of a later tutorial). Now press "Enter" to go to the next line and type "My name is Gary, and it's nice to meet you." The output will look like this: -``` +```output Hello World My name is Gary, and it's nice to meet you ``` @@ -49,7 +48,7 @@ Step 6. exit vi by typing ":q" You can also save and exit with one command, ":wq" It is important to remember that there are two basic operation modes in vi: the _command mode_, with which the user opens, saves and -exits from files, and the _insert_ mode with which the user inserts text—either by typing it in, or by copying and pasting—and can +exits from files, and the _insert_ mode with which the user inserts text-either by typing it in, or by copying and pasting-and can then edit any part of the text in the file. open file using `vi filename` diff --git a/getting-started/installation/secure-bootstrap.markdown b/getting-started/installation/secure-bootstrap.markdown index 92a3dfd85..56a564206 100644 --- a/getting-started/installation/secure-bootstrap.markdown +++ b/getting-started/installation/secure-bootstrap.markdown @@ -1,121 +1,249 @@ --- layout: default -title: Secure Bootstrap +title: Secure bootstrap published: true sorting: 20 -tags: [guide, installation, install, security] --- -This guide presumes that you already have CFEngine properly installed -and running on the policy hub, the machine that distributes the policy -to all the clients. It also presumes that CFEngine is installed, but not -yet configured, on a number of clients. +This guide assumes you already have a working CFEngine hub (installed and bootstrapped), and you have installed CFEngine on a client you want to securely connect to the hub (bootstrap). +See the [Getting started guide][Getting started] for an introduction to CFEngine and how to install it. -We present a step-by-step procedure to securely bootstrapping a -number of servers (referred to as *clients*) to the policy hub, over a -possibly unsafe network. +CFEngine's trust model is based on the secure exchange of keys. +Since it's using mutual authentication, this trust goes in both directions. +Both the client and the hub refuse to communicate with an unknown, untrusted host. +Usually, when getting started with CFEngine, this step is automated as a dead-simple "bootstrap" procedure: -## Introduction +```command +cf-agent --bootstrap +``` + +However, this is in the default configuration, and there are several limitations and implications of this; + +## Default configuration -CFEngine's trust model is based on the secure exchange of keys. This -exchange of keys between *client* and *hub*, can either happen manually -or automatically. Usually this step is automated as a dead-simple -"bootstrap" procedure: +In the default configuration, the policy server (`cf-serverd`) on the hub machine trusts incoming connections from the same `/16` subnet. +This means that: -`cf-agent --bootstrap $HUB_IP` +* Bootstrapping new clients will work as long as the 2 first numbers in the IP address are identical ([IPv4 dot decimal representation](https://en.wikipedia.org/wiki/Dot-decimal_notation)) . + The hub and client mutually accept each other's keys, automatically. +* This applies to _all_ IP addresses within that range, not just the 1 IP address belonging to the client you are currently bootstrapping. +* The hub will keep accepting new clients from those IP addresses until you change the configuration. +* If you try to bootstrap a client where those 2 numbers in the IP address do not match the hub, it will fail. -It is presumed that during this first key exchange, *the network is -trusted*, and no attacker will hijack the connection. After -"bootstrapping" is complete, the node can be deployed in the open -internet, and all connections are considered secure. +This situation, where the client and hub automatically transfer and trust each other's keys is called _automatic trust_ or _automatic bootstrap_. +When using automatic trust, it is presumed that during this first key exchange, *the network is trusted*, and no attacker will hijack the connection. +Below we will show ways to change the configuration and bootstrap your clients in more secure ways. +The goal here is to illustrate the different approaches, explaining what is needed and the implications of each. +In the end, you will not be running these commands manually, but rather putting them into a provisioning system. -However there are cases where initial CFEngine deployment is happening -over an insecure network, for example the Internet. In such cases we -already have a secure channel to the clients, usually ssh, and we use -this channel to *manually establish trust* from the hub to the clients -and vice-versa. +## Allowing only specific IP addresses / subnets -## Locking down the policy server +In order to specify and limit which hosts (IP addresses) are considered trusted and allowed to connect and fetch policy files, you can put the trusted IP addresses and subnets into the ```acl``` variable: -We must change the policy we're distributing to fully locked-down -settings. So after we have set-up our hub (using the standard procedure -of `cf-agent --bootstrap $HUB_IP`) we take care of the following: +```json +[file=/var/cfengine/masterfiles/def.json] +{ + "variables": { + "default:def.acl": ["192.0.2.42", "198.51.100.7"] + } +} +``` -* `cf-serverd` must never accept a connection from a client presenting an - untrusted key. [Disable automatic key trust][Masterfiles Policy Framework#trustkeysfrom] - by providing an empty list for `def.trustkeyfrom`. +**Important:** Replace `192.0.2.42` with the IP address of your hub, `198.51.100.7` with the IP address of your client, and extend the list with any additional IP addresses / subnets. -## Bootstrap without automatically trusting +If you are using CFEngine Build, you can use [this module](https://build.cfengine.com/modules/allow-hosts/), putting the IP addresses as module input, or add the json file above to your project. +(Save it as a file called `def.json` and do `cfbs add ./def.json`). -In order to securely bootstrap a host you must have the public key of the host -you wish to trust. +Once this is set, you are no longer using the default value explained above (the `/16` subnet). +This variable controls 3 different aspects: IP addresses allowed to connect, IP addresses to automatically trust keys from, and IP addresses allowed to fetch policy files. -Copy the hubs public key (`/var/cfengine/ppkeys/localhost.pub`) to the agent you -wish to bootstrap. And install it using `cf-key`. +At this point, you can run bootstrap on the client to the hub using automatic trust: -```console -[root@host001]# cf-key --trust-key /path/to/hubs/key.pub +```command +cf-agent --bootstrap 192.0.2.42 ``` -**Note:** If you are using [protocol_version `1` or `classic`][Components#protocol_version] -you need to supply an IP address before the path to the key. +If the IP addresses are correct, keys will be automatically exchanged, and hosts will start using encrypted communication over TLS, with mutual authentication. +At this point CFEngine works on your hub and client, even if they are not on the same `/16` subnet. +If this is your first time testing CFEngine, feel free to stop reading here and test the various features of Mission Portal, start writing policy, etc. +In the sections below, we will explore the security implications of this setup further, and show more secure approaches. + +**Tip:** Setting the variable to `["0.0.0.0/0"]` will open up your hub to all IPv4 addresses, the entire internet. +This is generally not recommended, but can make sense if you disable automatic trust (shown below), need to support clients connecting from the public internet, and/or want to manage firewalling restrictions outside of CFEngine. + +## Disabling automatic trust - Locking down the policy server -For example: +In all cases, it is recommended to disable automatic trust when you are not using it. +Either immediately after installation (if distributing keys through another channel, see below) or after you are done bootstrapping clients. +You can edit the augments file to achieve this: +```json +[file=/var/cfengine/masterfiles/def.json] +{ + "variables": { + "default:def.trustkeysfrom": [] + } +} ``` -notice: Establishing trust might be incomplete. For completeness, use --trust-key IPADDR:filename + +If you are using CFEngine Build, you can achieve this by adding [this module](https://build.cfengine.com/modules/disable-automatic-key-trust/), or adding the json file above to your project. + +When combined with the variable above, you can create a very restricted setup: + +```json +[file=/var/cfengine/masterfiles/def.json] +{ + "variables": { + "default:def.acl": ["192.0.2.42", "198.51.100.7"], + "default:def.trustkeysfrom": [] + } +} ``` -Next copy the hosts public key (`/var/cfengine/ppkeys/localhost.pub`) to the hub -and install it using `cf-key`. +Only those 2 IP addresses are allowed to connect, and they must use their existing keys, no new keys are automatically trusted. + +With what we've discussed up until now, we still need to _trust the network_ for limited periods of time, when we are bootstrapping new hosts. +(Assuming that we are really communicating with the host we intend to, and that there aren't additional malicious hosts connecting from the same IP addresses / subnets). +This is sometimes acceptable, especially if you are just testing CFEngine in a disposable and isolated environment. +However, in a production setup it is recommended to exchange keys in the most secure / trusted method available. +Below, we will show how. + +## Key location and generation -```console -[root@hub]# cf-key --trust-key /path/to/host001/key.pub +If you are installing CFEngine using one of our official packages, keys are automatically generated and you can see them in the expected location: + +```command +sudo ls /var/cfengine/ppkeys +``` +```output + localhost.priv + localhost.pub +'root-SHA=caa398e50c6e6ad554ea90e1bd5e8fee269ca097df6ce0c86ce993be16f6f9e3.pub' ``` -Now that the hosts trust each other we can bootstrap the host to the hub. +The keypair of the host itself is always in the `localhost.pub` and `localhost.priv` files. +Additional public keys from the hosts CFEngine is talking to over the network are in the other `.pub` files. +The filename has a SHA checksum of the public key file - this is the CFEngine hosts unique ID (in Mission Portal, our API, PostgreSQL and LMDB databases, etc.). + +**Recommendation:** Don't copy, transfer, open, or share the private key (`localhost.priv`). +It is a secret - putting it in more places is not necessary and increases the chances it could be compromised. +When distributing keys for establishing trust, we are distributing the public keys (`.pub` files). -```console -[root@host001]# cf-agent --trust-server no --bootstrap $HUB +If you are compiling CFEngine from source, or spawning a new VM based on a snapshot without keys inside, you can generate a new keypair: + +```command +sudo cf-key ``` -## Manually establishing trust +**Tip:** When using "golden images" to spawn machines with CFEngine already installed, ensure the keys in `/var/cfengine/ppkeys` are deleted before generating the snapshot, and generate / insert keys during provisioning. + +## Key distribution - boostrapping without automatically trusting + +To securely bootstrap a host to a hub, without trusting the network (IP addresses), you need to copy the 2 public keys across some trusted channel. +Below we will be using SSH as the trusted channel, however the commands can easily be translated to however you are able to run commands and transfer files to your hosts. +(This could be via memory stick, a management interface or some other out-of-band management solution). +The same applies to passwordless sudo - we're using sudo commands without password prompts below, if you have configured password prompts for sudo, or another way you need to run privileged commands, please adjust accordingly. -Get the hub's key and fingerprint, we'll them when configuring the host to trust -the hub: +Assuming you are sitting on a laptop / workstation, and have network and SSH access to both the client and the hub, first set up some variables for each of them: -```console -[root@hub]# HUB_KEY=`cf-key -p /var/cfengine/ppkeys/localhost.pub +```command +BOOTSTRAP_IP="192.0.2.42" HUB_SSH="ubuntu@192.0.2.42" CLIENT_SSH="ubuntu@198.51.100.7" ``` -### On each client we deploy +Edit the 3 variables according to your situation, they represent: -We will perform a *manual bootstrap*. +* `BOOTSTRAP_IP` - The IP address of the hub, which you want `cf-agent` on the client to bootstrap to (connect to). +* `HUB_SSH` - The username / IP combination you would use to connect to the hub with SSH. +* `CLIENT_SSH` - The username / IP combination you would use to connect to the hub with SSH. -* Get the client's key and fingerprint, we'll need it later when establishing - trust on the hub: +### Trusting the client's key on the hub - ```console - [root@host001]# CLIENT_KEY=`cf-key -p /var/cfengine/ppkeys/localhost.pub` - ``` +Inspect the key: -* Write the policy hub's IP address to `policy_server.dat`: +```command +ssh "$CLIENT_SSH" "sudo cat /var/cfengine/ppkeys/localhost.pub" +``` +```output +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEAt93D8fb+M7HGZxsVo+FnOhnLM9E0QCr046N369jOeePY65lPOhAD +nlWlDPJrYqhnobEdnFr/uNp0ydqb1EASe4qjhQUDi1ujz5+T9dTwhZqUfx22RM6D +CLulbdoXwImPOCNi157UBRIwYVJ6527rv0/TlTpS9iUQVStg0YCBEasGRcQfX/bU +DKrL5Ei+ukJtSEx11NlZ9tRYNu22mJYPGGpNJ0FbiHvR+eu7mAuUZ1QeddcuYkGP +H5/eIe0uTGOmFLXb4gUQymNLJUjQqxoO2l6Km4UpGj61871gCiqMGVTvvZWFbo+g +1KR3RS6L/Gqv9U89msZTGQafpjFQyVbYnwIDAQAB +-----END RSA PUBLIC KEY----- +``` - ```console - [root@host001]# echo $HUB_IP > /var/cfengine/policy_server.dat - ``` +It should have the format above, with `BEGIN RSA PUBLIC KEY`, the arbitrary data, and `END RSA PUBLIC KEY`. +When you're scripting / automating the copying of keys, you can add some checks for this. -* Put the hub's key into the client's trusted keys: +Download the key: - ```console - [root@host001]# scp $HUB_IP:/var/cfengine/ppkeys/localhost.pub /var/cfengine/ppkeys/root-${HUB_KEY}.pub - ``` +```command +ssh "$CLIENT_SSH" "sudo cat /var/cfengine/ppkeys/localhost.pub" > client.pub +``` -### Install the clients public key on the hub +Upload it to the hub: + +```command +scp ./client.pub "$HUB_SSH":client.pub +``` -* Put the client's key into the hub's trusted keys. So - on the hub, run: +And use `cf-key` to trust the key: + +```command +ssh "$CLIENT_SSH" "sudo cf-key --trust-key client.pub" +``` + +### Trusting the hub's key on the client + +Now, for the client we need to perform exactly the same steps: + +Inspect the key: + +```command +ssh "$HUB_SSH" "sudo cat /var/cfengine/ppkeys/localhost.pub" +``` +```output +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEAt8Wti90sRjLiEhLbC5096nEhzV3fU0N4TrxiGPCb26KufavBrXGw +vmzTeJoWnIFFSn7OYU1g59U7s4aViZwqQ647opc0gZo2dVjDTRFW8lB4dmS7SjAe +t8NA3iXQigWY+45TbvPOalNHurhyrJ4g1+0ttdqwk/L1fVkK0u9wmHrgfo+UQR0D +9P96GWnPKyzVp5PdMmfX0Sm6kMBurawRYeiFCq3gqGtkc0rj3FHr1afrM+8egP9D +sWl43NmMlZ8B9Yt2bP0wdNsbXC7vouDZg8sIQVfvcxSkla+kGceGrEmNTDPuGFlx +VknPhmpjMJ7XhvaXXR1btu3/PLjGLDj6SwIDAQAB +-----END RSA PUBLIC KEY----- +``` + +Download the key: + +```command +ssh "$HUB_SSH" "sudo cat /var/cfengine/ppkeys/localhost.pub" > hub.pub +``` + +Upload it to the client: + +```command +scp ./hub.pub "$CLIENT_SSH":hub.pub +``` + +And use `cf-key` to trust the key: + +```command +ssh "$CLIENT_SSH" "sudo cf-key --trust-key hub.pub" +``` + +### Start CFEngine on the client with a bootstrap command + +Now that keys are distributed, trust is established. +We can run the normal bootstrap command with one crucial difference: +`--trust-server no` tells the agent to **not** automatically trust an unknown key on the other end. +This will start the normal CFEngine services (`cf-execd`, `cf-serverd`, etc.): + +```command +ssh "$CLIENT_SSH" "cf-agent --trust-server no --bootstrap $BOOTSTRAP_IP" +``` - ```console - [root@hub]# scp $CLIENT_IP:/var/cfengine/ppkeys/localhost.pub /var/cfengine/ppkeys/root-${CLIENT_KEY}.pub - ``` +When we connect to the hubs IP address, if there is another server answering, a potential [man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack), it will not work. +The agent on the client machine will refuse to communicate with the untrusted server. +This is the main reason (security benefit) of doing mutual authentication and secure key distribution. diff --git a/getting-started/installation/upgrading.markdown b/getting-started/installation/upgrading.markdown index 10c8985f9..85bb337e1 100644 --- a/getting-started/installation/upgrading.markdown +++ b/getting-started/installation/upgrading.markdown @@ -13,7 +13,7 @@ In short, the steps are: 1. [Backup][Upgrading#Backup] 2. [Masterfiles Policy Framework upgrade][Upgrading#Masterfiles Policy Framework upgrade] -3. [Enterprise Hub binary upgrade][Upgrading#Enterprise Hub binary upgrade] +3. [Enterprise hub binary upgrade][Upgrading#Enterprise hub binary upgrade] 4. [Agent binary upgrade][Upgrading#Agent binary upgrade] **Notes:** @@ -25,6 +25,15 @@ In short, the steps are: compatibility. For example, a host running 3.15.0 will not be able to report to a hub running 3.12.3. +- Masterfiles Policy Framework (MPF) should always be newer than or equal to + your newest binary version. While things often work without performing the MPF + upgrade you may miss important changes where the policy has been instrumented + to account for changes in binary behavior. For example, if you upgraded to + 3.18.2 or later without upgrading your policy framework you would see many + warnings that the framework upgrade would have suppressed. That specific + change was detailed in this + [blog post about changes in behavior to directory permissions and the execute bit](https://cfengine.com/blog/2022/rxdirs-default-changing-from-true-to-false/). + ## Backup Backups are made during the hub package upgrade, but it's prudent to take a full @@ -65,7 +74,7 @@ anything goes wrong. root@hub:~# find /etc -name 'cfengine*' | tar cfz /tmp/$(date +%Y-%m-%d)-cfengine-init-backup.tar.gz -T - ``` - **See also:** [Hub administration backup and restore][Backup and Restore] + **See also:** [Hub administration backup and restore][Backup and restore] 3. Copy the archive to a safe location. @@ -93,12 +102,17 @@ Normally most files can be replaced with new ones, files that typically contain user modifications include `promises.cf`, `controls/*.cf`, and `services/main.cf`. -- [Masterfiles Policy Framework Upgrade Tutorial][Masterfiles Policy Framework Upgrade] +- [Masterfiles Policy Framework upgrade Tutorial][Masterfiles Policy Framework upgrade] Once the Masterfiles Policy Framework has been qualified and distributed to all agents you are ready to begin binary upgrades. -## Enterprise Hub binary upgrade +## Enterprise hub binary upgrade + +**Note:** Enterprise Hub packages want at least as much free space in the backup +directory (`/var/cfengine/state/pg/backup` by default) as what is currently +consumed in `/var/cfengine/state/pg/data`. Also, the backup directory should be +empty before performing an Enterprise Hub binary upgrade. 1. Ensure the CFEngine services are **running** @@ -119,6 +133,8 @@ agents you are ready to begin binary upgrades. backups made during upgrade are placed in `/var/cfengine/state/pg/backup`, this can be overridden by **exporting** `BACKUP_DIR` before package upgrade. + **NOTE:** `BACKUP_DIR` should not exist and should be removable (e.g. it should not be a direct mount point). + **Red Hat/CentOS:** ```console @@ -180,8 +196,8 @@ agents you are ready to begin binary upgrades. 3. Verify that the selected hosts are upgrading successfully. - - Mission Portal [Inventory reporting interface][Reporting UI#Inventory Management] - ![Inventory Management](Reports-Inventory-1.png) + - Mission Portal [Inventory reporting interface][Reporting UI#Inventory management] + ![Inventory management](Reports-Inventory-1.png) - [Inventory API][Inventory API] diff --git a/getting-started/installation/version-control.markdown b/getting-started/installation/version-control.markdown index e8c18ff96..51a9c59c4 100644 --- a/getting-started/installation/version-control.markdown +++ b/getting-started/installation/version-control.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Version Control +title: Version control published: true sorting: 60 -tags: [manuals, writing policy, version control, git, subversion] --- By default, CFEngine policy is published `/var/cfengine/masterfiles` on the policy @@ -16,7 +15,7 @@ CFEngine Enterprise ships with [masterfiles-stage](https://github.com/cfengine/core/tree/master/contrib/masterfiles-stage), tooling to assist with deploying policy from a version control system. -Enterprise users can configure automatic publication of policy from Mission Portal as described in [Policy Deployment] or by using the [VCS settings API][VCS settings API]. Community users can also install and use this tooling by following the +Enterprise users can configure automatic publication of policy from Mission Portal as described in [Policy deployment] or by using the [VCS settings API][VCS settings API]. Community users can also install and use this tooling by following the [installation instructions](https://github.com/cfengine/core/tree/master/contrib/masterfiles-stage#installation). ## Commit hooks @@ -36,7 +35,8 @@ We can use a Git update hook to prevent a change from being made unless it passes syntax checking. The idea is to check out the revision in a temporary directory and run `cf-promises` on it. Here is an example hook. -``` +```shell +[file=update] #!/bin/sh # --- Command line @@ -82,7 +82,8 @@ For subversion, the principle is essentially the same. Note that for a post-commit hook the check is run after update, so the repository may be left with a syntax error, but the committer is notified. -``` +```shell +[file=post-commit] #!/bin/sh REPOS="$1" diff --git a/getting-started/modules-from-cfengine-build.markdown b/getting-started/modules-from-cfengine-build.markdown index 91aa2163d..1b1a0788d 100644 --- a/getting-started/modules-from-cfengine-build.markdown +++ b/getting-started/modules-from-cfengine-build.markdown @@ -3,7 +3,6 @@ layout: default title: Modules from CFEngine Build published: true sorting: 20 -tags: [guide, getting started, modules] --- Now that you've installed CFEngine and the tools we need, we can start working with modules from CFEngine Build. @@ -21,13 +20,13 @@ There is a video version of this tutorial available on YouTube: Create a folder for you project, for example in your home directory: -``` +```command mkdir -p ~/cfengine_project ``` Initialize it: -``` +```command cd ~/cfengine_project && cfbs init ``` @@ -43,7 +42,7 @@ This is the default policy which is included in the CFEngine packages, so it is It is needed for various features of CFEngine and CFEngine Enterprise to work correctly. If you didn't add it as part of the previous `cfbs init`, add it now: -``` +```command cfbs add masterfiles ``` @@ -51,19 +50,19 @@ At this point, you can go to [build.cfengine.com](https://build.cfengine.com) an The command to add them is the same as above. For the purposes of this tutorial, let's add the git module so we can work with git repositories later: -``` +```command cfbs add git ``` Additionally, let's add a module to make CFEngine run policy and report collection every minute instead of the default 5 minute interval: -``` +```command cfbs add every-minute ``` Finally, let's add a report for whether the OS is supported by the OS vendor: -``` +```command cfbs add compliance-report-os-is-vendor-supported ``` @@ -71,13 +70,10 @@ cfbs add compliance-report-os-is-vendor-supported Once we are done adding modules, it is time to build them, combining it all into the policy set which will be deployed to our hub: -``` +```command cfbs build ``` - -Output: - -``` +```output Modules: 001 masterfiles @ a87b7fea6f7a88808b327730a4ba784a3dc664eb (Downloaded) 002 library-for-promise-types-in-python @ c3b7329b240cf7ad062a0a64ee8b607af2cb912a (Downloaded) @@ -117,14 +113,14 @@ Feel free to look at some of the files in `out/masterfiles/`, if you want to und Now, let's deploy what we built to the hub: -``` +```command cf-remote deploy ``` **Note:** This assumes your hub is saved in `cf-remote`, with the group name _hub_. We did this in the first part of the series, while installing CFEngine, but if you haven't you can do it like this: -``` +```command cf-remote save -H root@192.168.56.2 --role hub --name hub ``` @@ -157,16 +153,16 @@ Here are some examples of modules you might be interested in: To add more modules, just repeat the commands from steps 1-3. For example, add the `inventory-sudoers` module to your project: -``` +```command cfbs add inventory-sudoers ``` Then, as usual, build and deploy: -``` +```command cfbs build && cf-remote deploy ``` In the next tutorial we will look more at the reporting and Web UI, called Mission Portal: -[Reporting and Web UI][Reporting and Web UI] +[Reporting and web UI][Reporting and web UI] diff --git a/getting-started/reporting-and-web-ui.markdown b/getting-started/reporting-and-web-ui.markdown index 4f88498df..678a6addd 100644 --- a/getting-started/reporting-and-web-ui.markdown +++ b/getting-started/reporting-and-web-ui.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Reporting and Web UI +title: Reporting and web UI published: true sorting: 30 -tags: [guide, getting started, mission portal] --- After setting up your CFEngine Hub, adding modules and deployed your first policy set, it's appropriate to get familiar with the CFEngine Web UI, Mission Portal, and some of it's useful features. diff --git a/getting-started/writing-policy.markdown b/getting-started/writing-policy.markdown index 11e178e96..8db80a6ea 100644 --- a/getting-started/writing-policy.markdown +++ b/getting-started/writing-policy.markdown @@ -3,7 +3,6 @@ layout: default title: Writing policy published: true sorting: 40 -tags: [guide, getting started, mission portal] --- Now that we are familiar with how CFEngine works, and how you can use modules and the web UI, let's take a look at policy. @@ -11,13 +10,13 @@ CFEngine policy language is a flexible, declarative language for describing the To start, create a new file and open it, or the folder, in your editor: -``` +```command cd ~/cfengine_project && touch my_policy.cf ``` Open the project folder (or just the policy file) in your editor: -``` +```command code . ``` @@ -28,6 +27,7 @@ code . Let's take a look at the traditional "Hello, world!" example: ```cfengine3 +[file=my_policy.cf] bundle agent hello_world { files: @@ -50,7 +50,7 @@ With `files` promises you can manipulate file permissions, edit lines, render te Put the code snippet above in a file called `my_policy.cf`, and add it to the project: -``` +```command cfbs add ./my_policy.cf ``` @@ -59,20 +59,20 @@ The default is the first bundle, `hello_world`, which is what we want. Now, build and deploy again: -``` +```command cfbs build && cf-remote deploy ``` The policy has been deployed and that `/tmp/hello` file should be ready. You can log in with SSH to check this, or use `cf-remote`: -``` +```command cf-remote sudo -H hub "cat /tmp/hello" ``` The output should look like this: -``` +```output root@192.168.56.2: 'cat /tmp/hello' -> 'Hello, world!' ``` @@ -81,7 +81,7 @@ root@192.168.56.2: 'cat /tmp/hello' -> 'Hello, world!' In CFEngine, the program which runs all your policy / modules and makes changes to the system is called `cf-agent`, or _the agent_. Just like above, we can use `cf-remote sudo` to run the agent on the hub: -``` +```command cf-remote sudo -H hub "cf-agent --no-lock --info" ``` @@ -92,7 +92,7 @@ This is similar to triggering an agent run with the buttons in Mission Portal, o To test that our policy works, let's delete the `/tmp/hello` file and watch CFEngine create it: -``` +```command cf-remote sudo -H hub "rm /tmp/hello && cf-agent -KI" ``` @@ -102,6 +102,7 @@ Earlier in this tutorial series, we added the `promise-type-git` module to our p This means that we can just start using the new promise type in policy: ```cfengine3 +[file=my_policy.cf] bundle agent hello_world { git: @@ -114,7 +115,7 @@ bundle agent hello_world This policy uses the `git` promise type to clone the Hugo project's source code from GitHub. Again, put the code snippet above in the `my_policy.cf` file, build, and deploy: -``` +```command cfbs build && cf-remote deploy ``` @@ -133,6 +134,7 @@ This has several benefits: Here is a simple example: ```cfengine3 +[file=my_policy.cf] bundle agent hello_world { vars: @@ -159,7 +161,7 @@ We might want to have some version information on which hugo we are using. Since we clone and track the `master` branch, there isn't necessarily a version number available, but there is always a commit SHA, so let's look for that. From the command line, you could find this by: -``` +```command git log -1 --format="%H" ``` @@ -167,6 +169,7 @@ We want to put this in a variable and include it in our reports we can see in Mi To take the output of a command and put it in a variable, we will use the `execresult()` function: ```cfengine3 +[file=my_policy.cf] bundle agent hello_world { vars: @@ -212,6 +215,6 @@ Next, we will look at implementing modules, such as the git promise type we used If you would like to learn more about policy writing, these are some good resources to look at: -* [Language concepts][Language Concepts] -* [Promise Types][Promise Types] +* [Language concepts][Language concepts] +* [Promise types][Promise types] * [Functions][Functions] diff --git a/guide.markdown b/guide.markdown index 9b636e442..d5018d855 100644 --- a/guide.markdown +++ b/guide.markdown @@ -9,9 +9,9 @@ CFEngine is a configuration management system that provides a framework for auto CFEngine is decentralized and highly scalable. It is powered by autonomous agents that can continuously monitor, self-repair, and update or restore an entire IT system, with negligible impact on system resources or performance. -See Also: [Overview][Overview] +See also: [Overview][Overview] -## CFEngine Features ## +## CFEngine features ## * Defines the configuration of an entire IT system, including: Devices, Users, Applications, and Services. * Helps maintain that system over time. @@ -19,7 +19,7 @@ See Also: [Overview][Overview] * Ensures compliance with a desired system state. * Propagates real-time modifications or updates across the system. -## Choose a CFEngine Version +## Choose a CFEngine version [CFEngine Enterprise](https://cfengine.com/product-overview/) is a licensed edition for enterprises that plan to use the tool in production environments. The Enterprise edition comes in several variants, including one that can be evaluated for free (up to 25 servers). @@ -31,47 +31,47 @@ CFEngine Community, a free GPL v3 open source edition. See also: -* [Supported Platforms and Versions][Supported Platforms and Versions] +* [Supported platforms and versions][Supported platforms and versions] -## Install It +## Install it [%CFEngine_include_markdown(include-install-bootstrap-configure-summary.markdown)%] See [Installation][Installation] for a more detailed guide on how to get CFEngine up and running for various environments. -## Try It +## Try it Walk through the examples, tutorials and how to guides to get a better feel for the power and value of CFEngine: -* [Policy Examples and Tutorials][Examples and Tutorials] +* [Policy Examples and tutorials][Examples and tutorials] -## Learn More +## Learn more -Take a look at the [Getting Started][] section to learn more about CFEngine's architecture and components, as well as how to write policy that can help manage IT systems. +Take a look at the [Getting started][] section to learn more about CFEngine's architecture and components, as well as how to write policy that can help manage IT systems. Check out [External resources][External resources], for more guides, demos, and other resources from our CFEngine staff and our special CFEngine contributors. -## Use our Help +## Use our help -[Support and Community][External Resources#Support and Community] We provide a number of ways to connect you to CFEngine +[Support and community][External Resources#Support and community] We provide a number of ways to connect you to CFEngine experts if you need more help. Contact us! -## CFEngine Guide ## +## CFEngine guide ## * [Overview][] -* [Release Notes][] +* [Release notes][] * [Installation][] - * [Pre-Installation Checklist] - * [General Installation] + * [Pre-installation checklist] + * [General installation] * [Upgrading] - * [Secure Bootstrap] -* [Writing and Serving Policy][] - * [Language Concepts][] - * [Promises Available in CFEngine][] - * [Authoring Policy Tools & Workflow][] + * [Secure bootstrap] +* [Writing and serving policy][] + * [Language concepts][] + * [Promises available in CFEngine][] + * [Authoring policy tools & workflow][] * [Reports][] * [FAQ][] * [External Resources][] diff --git a/guide/introduction/security-overview.markdown b/guide/introduction/security-overview.markdown deleted file mode 100644 index 8d07021a5..000000000 --- a/guide/introduction/security-overview.markdown +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: default -title: Security Overview -sorting: 7 -published: false -tags: [overviews, security overview] ---- - - -## Security and CFEngine ## diff --git a/include-install-bootstrap-configure-summary.markdown b/include-install-bootstrap-configure-summary.markdown index ad35af4d9..66109948a 100644 --- a/include-install-bootstrap-configure-summary.markdown +++ b/include-install-bootstrap-configure-summary.markdown @@ -4,7 +4,7 @@ There are several steps to bring up a CFEngine installation within an organizati 2. Configure your network and security. 3. Download the CFEngine software. 4. Install CFEngine on the Policy Server(s). -5. Bootstrap the Policy Server to itself. +5. Bootstrap the policy server to itself. 6. Initiate post-install configuration on the Policy Server. 7. Install CFEngine on the Host machine(s). 8. Bootstrap the Host(s) to a Policy Server. diff --git a/index.markdown b/index.markdown index 900acf0d9..ea3b675b5 100644 --- a/index.markdown +++ b/index.markdown @@ -8,9 +8,9 @@ alias: index.html ---
    -

    Welcome to CFEngine Documentation

    +

    Welcome to the CFEngine Documentation

    - This site contains information on how to manage and automate the infrastructure with CFEngine. + This site contains information on how to manage and automate infrastructure with CFEngine. It includes the reference for the following versions of CFEngine:
      @@ -29,7 +29,7 @@ alias: index.html
      Use modules to easily add reports or get things done without writing any code.
    • - Reporting and Web UI + Reporting and web UI
      Know more about your infrastructure and hosts, their data, compliance and make changes from within the Web UI.
    • @@ -38,7 +38,7 @@ alias: index.html
    • Developing modules -
      Turn your policy, reoprts, or python code into CFEngine Build modules for others to use.
      +
      Turn your policy, reports, or python code into CFEngine Build modules for others to use.
    • Tutorial series on policy language @@ -53,21 +53,21 @@ alias: index.html
    • API reference -
      The API is a conventional REST API which supports one or more GET, PUT, POST, or DELETE operations.
      +
      The API is a conventional REST API which supports HTTP GET, PUT, POST, and DELETE operations.
    • Language concepts -
      Learn Bundles, Bodies, Promises, Classes and Decisions, Variables, etc.
      +
      Learn about bundles, bodies, promises, variables, classes and decisions.
    • - Manage packages -
      Learn how to install, manage and remove packages using CFEngine.
      + Package management +
      Learn how to install, manage, and remove packages using CFEngine.
    • CFEngine Build
      - CFEngine Build is a catalogue of policy and modules created by CFEngine, our partner and community that - helps you to simplify the automation process. + CFEngine Build is a catalog of policy and modules created by CFEngine, our partners and community which + helps you simplify the automation process.
      Go to the page
    • diff --git a/legal.markdown b/legal.markdown deleted file mode 100644 index e2d984b59..000000000 --- a/legal.markdown +++ /dev/null @@ -1,72 +0,0 @@ ---- -layout: default -title: Legal and Licenses -published: false -sorting: 999 -alias: legal.html ---- - -## General Legal Disclaimer - -Please note that CFEngine is offered on an "as is" basis without warranty of -any kind, and that our products are not error or bug free. To the maximum -extent permitted by applicable law, CFEngine on behalf of itself and its -suppliers, disclaims all warranties and conditions, either express or implied, -including, but not limited to, implied warranties of merchantability, fitness -for a particular purpose, title and non-infringement with regard to the -Licensed Software. - -## CFEngine Documentation License - -The documentation is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](https://creativecommons.org/licenses/by-sa/3.0/deed.en_US). - -## 3rd Party Licenses and Libraries - -CFEngine includes the following 3rd party libraries and components: - -### Community - -* [libacl](http://savannah.nongnu.org/projects/acl) under the [LGPL](http://git.savannah.gnu.org/cgit/acl.git/tree/include/acl.h) -* [libattr](http://savannah.nongnu.org/projects/attr) under the [LGPL](http://git.savannah.gnu.org/cgit/attr.git/tree/include/libattr.h) -* [libcrypto](http://www.openssl.org/docs/crypto/crypto.html) under the [LGPL](http://api.libssh.org/master/libcrypto_8h_source.html) -* [libexpat](http://sourceforge.net/projects/expat/) under the [MIT License](http://opensource.org/licenses/mit-license.html) -* [libpam](http://www.linux-pam.org) as per the [copyright notice](https://git.fedorahosted.org/cgit/linux-pam.git/tree/Copyright) -* [libvirt](http://libvirt.org/FAQ.html) under the [LGPL version 2.1](http://www.opensource.org/licenses/lgpl-license.html) -* [libxml2](http://xmlsoft.org/FAQ.html) under the [MIT license](http://opensource.org/licenses/mit-license.html) -* [LMDB](http://symas.com/mdb/) under the [OpenLDAP Public License](http://www.openldap.org/software/release/license.html) -* [OpenSSL](http://www.openssl.org) under the [OpenSSL license](http://www.openssl.org/source/license.html) -* [PCRE](http://www.pcre.org) under the [PCRE license](http://www.pcre.org/licence.txt) -* [PEG](http://piumarta.com/software/peg/) under the MIT license -* [QDBM](http://sourceforge.net/projects/qdbm/) under the [GNU Library or Lesser General Public License 2.0 (LGPLv2)](http://www.opensource.org/licenses/lgpl-license.html) -* [TokyoCabinet](http://fallabs.com/tokyocabinet/) under the [GNU Lesser General Public License](http://www.opensource.org/licenses/lgpl-license.html) -* [Zlib](http://www.zlib.net) under the [zlib license](http://www.zlib.net/zlib_license.html) - -### Enterprise - -* [Angular.js](https://angularjs.org) through [MIT Licence](https://github.com/angular/angular.js/blob/master/LICENSE) -* [Apache](http://httpd.apache.org) under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) -* [APR and APR-util](https://apr.apache.org) under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) -* [Chosen](http://harvesthq.github.io/chosen/) under the [MIT License](https://github.com/harvesthq/chosen/blob/master/LICENSE.md) -* [CodeIgniter](http://codeigniter.com/) under the [CodeIgniter License Agreement](http://ellislab.com/codeigniter/user-guide/license.html) -* [Disphelper](http://disphelper.sourceforge.net) (only Windows) under the [BSD](http://opensource.org/licenses/bsd-license.php) -* [Flot](http://www.flotcharts.org/) under a [permissive license](https://github.com/flot/flot/blob/master/LICENSE.txt) -* [Font Awesome](http://fontawesome.io) by Dave Gandy - http://fontawesome.io/license/ -* [git](http://git-scm.com) under the [GNU General Public License, version 2 (GPLv2)](http://opensource.org/licenses/GPL-2.0) -* [Glyphicons](http://glyphicons.com/license/) under [Creative Commons Attribution 3.0 Unported (CC BY 3.0)](http://creativecommons.org/licenses/by-sa/3.0/deed.en_US) -* [HighCharts](http://www.highcharts.com/) under the OEM license by HighSoft -* [jQuery](https://jquery.org) under the [MIT license](http://en.wikipedia.org/wiki/MIT_License) -* [libcurl](http://curl.haxx.se) under the [MIT/X derivative license](http://curl.haxx.se/docs/copyright.html) -* [libmcrypt](http://mcrypt.sourceforge.net) under the [LGPLv2](http://www.opensource.org/licenses/lgpl-license.html) -* [mod_ssl](http://www.modssl.org) under a BSD style license -* [oauth2-server-php](https://github.com/bshaffer/oauth2-server-php) under the [MIT License](https://github.com/bshaffer/oauth2-server-php/blob/develop/LICENSE) -* [OpenLDAP and liblber](http://www.openldap.org) under the [OpenLDAP Public License](http://www.openldap.org/software/release/license.html) -* [PHP](http://php.net) under the [PHP license version 3.01](http://www.php.net/license/3_01.txt) -* [php-apc](http://pecl.php.net/package/APC) under the [PHP License](http://www.php.net/license/3_01.txt) -* [PostgreSQL, libecpg and libecpg_compat](http://www.postgresql.org) under the [PostgreSQL License](http://opensource.org/licenses/postgresql) -* [redis](http://redis.io) under the [three clause BSD license](http://redis.io/topics/license) -* [rsync](http://rsync.samba.org) under the [GPLv3](http://rsync.samba.org/GPL.html) -* [Twitter Bootstrap Framework](http://getbootstrap.com) under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) -* [Bootstrap Icons](https://icons.getbootstrap.com) under the [MIT license](https://github.com/twbs/icons/blob/main/LICENSE.md) -* [underscore.js](http://underscorejs.org) under the MIT license - - diff --git a/overview.markdown b/overview.markdown index cc6757215..96c18c0c8 100644 --- a/overview.markdown +++ b/overview.markdown @@ -7,7 +7,7 @@ sorting: 10 CFEngine is a distributed system for managing and monitoring computers across an IT network. Machines on the network that have CFEngine installed, and have registered themselves with a policy server (see [Installation][Installation]), will each be running a set of CFEngine component applications that manage and interpret textual files called policies. Policy files themselves contain sets of instructions to ensure machines on the network are in full compliance with a defined state. At the atomic level are sets, or *bundles*, of what are known in the CFEngine world as [Promises][Promises]. *Promises* are at the heart of Promise Theory, which is in turn what CFEngine is all about. -## Policy Language and Compliance ## +## Policy language and compliance ## For many users, CFEngine is simply a configuration tool - i.e. software for deploying and patching systems according to a policy. Policy is described using promises. Every statement in CFEngine 3 is a promise to be kept at some time or location. More than this, however, CFEngine is not like other automation tools that "roll out" an image of some software once and hope for the best. Every promise that you make in CFEngine is continuously verified and maintained. It is not a one-off operation, but a self-repairing process should anything deviate from the policy. @@ -19,17 +19,17 @@ Those policies are distributed across all hosts within the system via download f CFEngine continually monitors all of the hosts in real-time, and should the system's current state begin to drift away from the intended state then CFEngine will automatically take corrective action to bring everything back into compliance. -See Also: [Language Concepts][], [Writing and Serving Policy][] +See also: [Language concepts][], [Writing and serving policy][] -## CFEngine Policy Servers and Hosts ## +## CFEngine policy servers and hosts ## There are basically two categories of machines in a CFEngine environment: policy servers and their client hosts. Policy servers are responsible for making policy files available to each of the client hosts that have registered with it (a.k.a. bootstrapped), including itself. Hosts on the other hand are responsible for ensuring they continuously pull in the latest policies, or changes to policies, from the policy server. They are additionally responsible for ensuring they remain fully compliant with the instructions contained within the policy files, at all times. The role of a particular machine where CFEngine is deployed determines which of the components will be installed and running at any given moment. -See Also: [Writing and Serving Policy][] +See also: [Writing and serving policy][] -## CFEngine Component Applications and Daemons ## +## CFEngine component applications and daemons ## There are a number of components in CFEngine, with each component performing a unique function: components responsible for implementing promises, components @@ -47,7 +47,7 @@ All CFEngine software components exist in `/var/cfengine/bin`. ![Components overview](components-overview.png) * [Daemons][Overview#Daemons] -* [Other Applications][Overview#Other Component Applications] +* [Other Applications][Overview#Other component applications] ### Daemons ### @@ -81,7 +81,7 @@ information to CFEngine from outside. This daemon authenticates requests from the network and processes them according to rules specified in the -[server control body][cf-serverd#Control Promises] and server bundles +[server control body][cf-serverd#Control promises] and server bundles containing [access promises][access]. See also: [cf-serverd][cf-serverd] reference documentation. @@ -94,7 +94,7 @@ See also: [cf-serverd][cf-serverd] reference documentation. See also: [cf-monitord][cf-monitord] reference documentation. -### Other Component Applications ### +### Other component applications ### * [/var/cfengine/bin/cf-agent][Overview#cf-agent] * [/var/cfengine/bin/cf-key][Overview#cf-key] diff --git a/overview/client-server-communication.markdown b/overview/client-server-communication.markdown index baef4c1c9..9c92d4aa2 100644 --- a/overview/client-server-communication.markdown +++ b/overview/client-server-communication.markdown @@ -3,13 +3,12 @@ layout: default title: Client server communication published: true sorting: 30 -tags: [overviews, troubleshooting, connectivity, network, server, access, remote, keys, encryption, security] --- Starting `cf-serverd` sets up a line of communication between hosts. This daemon authenticates requests from the network and processes them according to rules specified in the -[`server control`][cf-serverd#Control Promises] body and server bundles +[`server control`][cf-serverd#Control promises] body and server bundles containing `access` promises. The server can allow the network to access files or to execute CFEngine: @@ -43,7 +42,7 @@ In order to connect to the CFEngine server you need: run `cf-key`. * **Network connectivity** with an IPv4 or IPv6 address. * **Permission to connect** to the server. - The [`server control`][cf-serverd#Control Promises] body must grant access + The [`server control`][cf-serverd#Control promises] body must grant access to your computer and public key by name or IP address, by listing it in the appropriate access lists (see below). * **Mutual key trust**. @@ -64,7 +63,7 @@ variety of forms, usually files, but sometimes console output. ## Bootstrapping -[Bootstrap][General Installation#Bootstrap] is the manual first run of cf-agent that establishes +[Bootstrap][General installation#Bootstrap] is the manual first run of cf-agent that establishes communication with the policy server. Bootstrapping executes the `failsafe.cf` policy that connects to the server, establishes trust to the server's key, and that starts the @@ -194,7 +193,7 @@ authentication. Secrets should not be transferred through policy, encrypted or not. Policy files should be considered public, and any leakage should not reveal secret information. -**Note:** Connections from the cf-agent are cached as described in the +**Note:** Connections from the `cf-agent` are cached as described in the documentation for body [`copy_from`][files#copy_from]. ### Protocol Classic @@ -209,18 +208,18 @@ and server hosts. After the initial connection is established subsequent connections and data transfer is encrypted by a randomly generated Blowfish key that is refreshed each session. -With the classic protocol cf-serverd has the ability to enforce that a +With the classic protocol `cf-serverd` has the ability to enforce that a file transfer be encrypted by setting the [`ifencrypted` access attribute][access#ifencrypted]. When ACLs that -require encryption have unencrypted access attempts cf-serverd logs an +require encryption have unencrypted access attempts `cf-serverd` logs an error message indicating the file requires encryption. Access to files -that cf-serverd requires to be encrypted can be logged by setting the +that `cf-serverd` requires to be encrypted can be logged by setting the [body server control `logencryptedtransfers` attribute][cf-serverd#logencryptedtransfers]. ### Protocol 2 3.6 introduced a new protocol option for communication with -cf-serverd. [Protocol 2][Components#protocol_version] +`cf-serverd`. [Protocol 2][Components#protocol_version] is the default in 3.7+ and uses a TLS session for encryption. **Note:** When protocol 2 is in use legacy encryption attributes are **noop**. @@ -234,21 +233,21 @@ The following attributes are affected: The specific encryption algorithm used depends on the cipher negotiated between the client and the server. You can control which -ciphers are allowed by cf-serverd for **incoming** connections by +ciphers are allowed by `cf-serverd` for both **incoming** and **outgoing** (in the case of client initiated reporting in CFEngine Enterprise) connections by setting the [body server control `allowciphers` attribute][cf-serverd#allowciphers]. Controlling -which ciphers are allowed to be used in **outgoing** connections is +which ciphers are allowed to be used by `cf-agent` is done by setting [body common control `tls_ciphers`][Components#tls_ciphers]. -Additionally the minimum version of TLS required for **incoming** +Additionally the minimum version of TLS required for **incoming** and **outgoing** (in the case of client initiated reporting in CFEngine Enterprise) connections can be set in [body server control `allowtlsversion`][cf-serverd#allowtlsversion] -and the minimum version of TLS required for **outgoing** connections -can be set in +and the minimum version of TLS required for connections +from `cf-agent` can be set in [body common control `tls_min_version`][Components#tls_min_version]. -There are debug and verbose level logs produced by cf-agent to +There are debug and verbose level logs produced by `cf-agent` to indicate when TLS is in use. The following was captured by running the agent update policy in debug @@ -269,9 +268,9 @@ verbose: Server is TRUSTED, received key 'SHA=5d20c01e4230aa53863eb36686eaa88209 debug: TLSRecvLines(): OK WELCOME USERNAME=root ``` -cf-serverd emits verbose and debug log messages indicating when TLS is in use. +`cf-serverd` emits verbose and debug log messages indicating when TLS is in use. -The following was captured by starting cf-serverd in the foreground +The following was captured by starting `cf-serverd` in the foreground with debug mode. `/var/cfenigne/bin/cf-serverd -Fd` @@ -312,7 +311,7 @@ information which might be useful to them. There is a simple checklist for curing this problem: 1. Make sure that you have granted access to the client's address in the - [`server control`][cf-serverd#Control Promises] body. + [`server control`][cf-serverd#Control promises] body. 2. Make sure the connecting client is granted access to the requested resources (files usually) in the `access_rules` promise bundle. 3. See the verbose log of the server for the exact error message, since the diff --git a/overview/directory-structure.markdown b/overview/directory-structure.markdown index 82038bc01..36598c8cd 100644 --- a/overview/directory-structure.markdown +++ b/overview/directory-structure.markdown @@ -1,26 +1,12 @@ --- layout: default -title: CFEngine Directory Structure +title: CFEngine directory structure published: true sorting: 20 -tags: [guide, system, system overview, directory structure, directories, files] --- The CFEngine application is fully contained within the /var/cfengine directory tree. Here is a quick breakdown of the directory structure and some of the files and functions associated with each subdirectory. -* [/var/cfengine/bin][CFEngine Directory Structure#/var/cfengine/bin] -* [Directories for Policy Files][CFEngine Directory Structure#Directories for Policy Files] -* [Output Directories][CFEngine Directory Structure#Output Directories] -* [Log Files in /var/cfengine][CFEngine Directory Structure#Log Files in /var/cfengine] -* [Database Files in /var/cfengine][CFEngine Directory Structure#Database Files in /var/cfengine] -* [Process (AKA PID) Files in /var/cfengine][CFEngine Directory Structure#Process (AKA PID) Files in /var/cfengine] -* [Sockets in /var/cfengine][CFEngine Directory Structure#Sockets in /var/cfengine] -* [Datafiles in /var/cfengine][CFEngine Directory Structure#Datafiles in /var/cfengine] -* [Binary Files in /var/cfengine][CFEngine Directory Structure#Binary Files in /var/cfengine] -* [git in /var/cfengine/bin][CFEngine Directory Structure#git in /var/cfengine/bin] -* [Misc. in /var/cfengine/bin][CFEngine Directory Structure#Misc. in /var/cfengine/bin] -* [Postgres in /var/cfengine/bin][CFEngine Directory Structure#Postgres in /var/cfengine/bin] - ## /var/cfengine/bin ## ### Agents ### @@ -38,9 +24,9 @@ The CFEngine application is fully contained within the /var/cfengine directory t * `runalerts.sh`: Updates Mission Portal status and activates alert actions (Enterprise only) * `cf-hub`: Responsible for collecting reports from remote agents. (CFEngine Enterprise only) -See Also: [CFEngine Component Applications and Daemons][Overview#CFEngine Component Applications and Daemons] +See also: [CFEngine component applications and daemons][Overview#CFEngine component applications and daemons] -## Directories for Policy Files ## +## Directories for policy files ## ### /var/cfengine/modules ### @@ -59,7 +45,7 @@ clients when they need to update their policies. Policies obtained from local policy execution. The `cf-agent` executable does not execute policies directly from this repository. -## Output Directories ## +## Output directories ## ### /var/cfengine/outputs ### @@ -79,7 +65,13 @@ should delete these files after a time to avoid a build up. State data such as current process identifiers of running processes, persistent classes and other cached data. -### /var/cfengine/lastseen ### +* `/var/cfengine/state/promise_execution.log`: In CFEngine Enterprise `cf-agent` writes promise execution results to this temporary file during execution. When `cf-agent` exits this data is stored for use by the reporting subsystem and the file is purged. + +* `/var/cfengine/state/variable.cache.tmp`: In CFEngine Enterprise as `cf-agent` executes information about variables are stored in this file. When `cf-agent` exits this data is stored for use by the reporting subsystem and the file is purged. + +* `/var/cfengine/state/context.cache.tmp`: In CFEngine Enterprise as `cf-agent` executes, information about classes that are defined are stored in this file. When `cf-agent` exits this data is stored for use by the reporting subsystem and the file is purged. + +### /var/cfengine/lastseen Log data for incoming and outgoing connections. @@ -141,27 +133,36 @@ In CFEngine Enterprise, a list of promises, with handles and comments, that were A time-stamped log of the percentage fraction of promises kept after each run. -## Database Files in /var/cfengine ## +## Database files in /var/cfengine ## + +### state/cf_classes.lmdb -* bundles.lmdb -* `cf_classes.lmdb` +A database of classes that have been defined on the current host, including +their relative frequencies, scaled like a probability. -A database of classes that have been defined on the current host, -including their relative frequencies, scaled like a probability. +### state/cf_lastseen.lmdb -* `cf_lastseen.lmdb` +A database of hosts that last contacted this host, or were contacted by this +host, and includes the times at which they were last observed. -A database of hosts that last contacted this host, or were contacted by -this host, and includes the times at which they were last observed. +### state/cf_lock.lmdb -* `checksum_digests.lmdb` +A database of active and inactive promise locks and their expiry times. Deleting +this database will reset all lock protections in CFEngine. + +**Note:** Locks are purged in order to maintain the integrity and health of the +underlying lock database. When the lock database utilization grows to 25% +locks 4 weeks or older are purged. At 50% locks 2 weeks or older are purged +and at 75% locks older than 1 week are purged. + +### state/cf_changes.lmdb The database of hash values used in CFEngine's change management functions. -* `nova_agent_execution.lmdb` -* `nova_track.lmdb` -* `performance.lmdb` +### state/nova_agent_execution.lmdb +### state/nova_track.lmdb +### state/performance.lmdb A database of last, average and deviation times of jobs recorded by `cf-agent`. Most promises take an immeasurably short time to check, but @@ -169,10 +170,10 @@ longer tasks such as command execution and file copying are measured by default. Other checks can be instrumented by setting a `measurement_class` in the `action` body of a promise. -## Process (AKA PID) Files in /var/cfengine ## +## Process (AKA PID) files in /var/cfengine ## The CFEngine components keep their current process identifier number in -`pid files' in the work directory. +_pid files_ in the work directory. * `cf-execd.pid` * `cf-hub.pid` @@ -189,7 +190,7 @@ The CFEngine components keep their current process identifier number in IP address of the policy server -## Binary Files in /var/cfengine ## +## Binary files in /var/cfengine ## * `randseed` @@ -239,12 +240,7 @@ IP address of the policy server * `bin/vacuumdb` -## Not Verified ## - -* `state/cf_lock.lmdb` - -A database of active and inactive locks and their expiry times. Deleting -this database will reset all lock protections in CFEngine. +## Not verified ## * `state/history.lmdb` diff --git a/overview/glossary.markdown b/overview/glossary.markdown index b79366a5f..8656267da 100644 --- a/overview/glossary.markdown +++ b/overview/glossary.markdown @@ -3,122 +3,323 @@ layout: default title: Glossary sorting: 50 published: true -tags: [guide, glossary] --- -#### Agent #### +#### Agent -A program that runs independently and automatically to carry out a task (think software robot). In CFEngine, the agent is called cf-agent and is responsible for making changes to computers. +A piece of software that runs independently and automatically to carry out a task (think software robot). +In CFEngine, the agent is called `cf-agent` and is responsible for making changes to computers. -(Originally, the word *robot*, meaning "servile worker," was coined -for the influential Czech writer Karel Čapek's play R.U.R by his -brother. The characters in that play are capable of fairly independent -thought, so the original sense of the word is apt to describe -CFEngine's agents as well.) +Historically, all the hosts in the infrastructure which are not hubs / policy servers have been referred to as agents. +The preferred terms to distinguish between the different roles are hub and client. +See CFEngine roles. -#### Authentication #### -#### Body #### +#### Body -A promise body is the description of exactly what is promised (as opposed to what/who is making the promise). The term `body' is used in the CFEngine syntax to mean a small template that can be used to contribute as part of a larger promise body. +A promise body is the description of exactly what is promised (as opposed to what/who is making the promise). +The term `body` is used in the CFEngine syntax to mean a small template that can be used to contribute as part of a larger promise body. -#### Bootstrap #### -#### Bundles for Knowledge #### -#### Bundle #### +#### Bootstrap + +After installing the CFEngine package, the software does not automatically start running. +It is missing some information, most notably where it should be fetching policy from. +In order to start CFEngine, you run the bootstrap command on all hosts in the infrastructure, with the IP address of the hub as an argument: + +```console +cf-agent --bootstrap +``` + +After running this command, CFEngine knows where (which IP address) to use when fetching policy. +It can also infer its CFEngine role (hubs fetch policy from themselves, while clients fetch policy from a hub). +Having this information, CFEngine can start the various components in the background, ensuring that policy is fetched, enforced, and reported regularly, every 5 minutes by default. + +#### Bundle In CFEngine, a bundle refers to a collection of promises that has a name. -#### Call Collect #### -#### Classes #### +#### Contend driven policy (CDP) + +A way of simplifying the way users provide information to CFEngine about policy by hiding the overhead of policy coding. +A CDP is a set of promises designed to solve a particular task in a standard way. +Users provide only a little data in the form of a simple spreadsheet of data in a table. + +#### CFEngine + +CFEngine comes from a contraction of _ConFiguration Engine_ and is maintained by Northern.tech (previously the CFEngine company). + +#### CFEngine 3.x + +Major version 3 of the CFEngine software was initiated in 2008 and is maintained to the present day. +It comes in both Enterprise and Open Source Community editions. + +#### CFEngine Community + +Free and Open Source edition of the CFEngine software, published under the GPL3 license, and optionally under the COSL license. + +#### CFEngine Enterprise + +Refers to commercial (paid) editions of the CFEngine software. + +#### CFEngine Nova + +An older name for CFEngine Enterprise, which is no longer used. +See CFEngine Enterprise. + +#### CFEngine role + +As far as CFEngine is concerned, all hosts in your infrastructure can be thought of as having one of two possible roles. +The CFEngine role describes how a specific host interacts with other installations of CFEngine on other hosts. + +The hub is the centralized place which serves policy and collects reports. +When starting out / for smaller infrastructures, it is common to have just 1 hub. +For larger / more complex infrastructures, multiple hubs are common. +Due to the multiple purposes this host serves, it is sometimes referred to as the policy server or the report collector, however _hub_ is the preferred term. + +Clients are all the other hosts which fetch policy from the hub and deliver reporting data back. +In a typical setup, all hosts which are not hubs are considered clients. +Historically, clients were sometimes referred to as agents, however this can be confusing, as agent also refers to the software component `cf-agent` which is installed on all hosts, not just the clients. + +Hub and client are the preferred terms when talking about the role a host performs, and which type of package to install on it. +See hub and client. + +#### Changelog + +A file used to describe the changes made since the last version of the software. + +#### Class + +Classes are used to classify a system (or the state of it) and to make decisions in CFEngine policy. +Classes are sometimes referred to as contexts. + +#### Class expressions + +Multiple classes separated by operators (and, or) to make more complex decisions. + +#### Class guards + +Used to restrict when / where promises are evaluated. +Appear in front of promises in CFEngine policy, consisting of a class expression followed by two colons. +Class guards are sometimes called context class expressions. + +#### Client + +In traditional computer networks and software, the client is the program which connects to a server, i.e., the software which initiates the connection in a networked system. +We say that a server is listening for incoming connections, and servers frequently serve thousands or even millions of clients simultaneously. + +In CFEngine, we use the word client to describe all of the hosts which are not hubs. +A CFEngine hub runs a policy server, which all clients connect to in order to fetch policy. + +Historically, the term agent has sometimes been used for this same meaning. +However, agent also refers to the agent component (the `cf-agent` binary), and thus, when discussing the role of a CFEngine host, _client_ is the preferred term for these hosts which are not hubs, and which packages to install on them. + +#### Client initiated reporting + +A mode where you change the configuration so that the hub does not initiate connections to client hosts to fetch reports. +Instead, the clients will establish a connection, and leave it open, until the hub is ready to use it to query for reporting data. +Sometimes referred to as call collect. + +#### Configuration management database (CMDB) + +A term coined as part of the IT Infrastructure Library (ITIL) as an outgrowth of an inventory database. + +#### Code branch + +The development of software is a branching process. +At certain times, the software code splits into different versions following different paths. +Each path needs to be maintained separately for a while. +This often happens when a release is made, because one wants to freeze the development of a public release (allowing only for some minor bug fixes), while continuing to add features to a branch leading to future versions. + +#### Components + +Standalone applications include `cf-agent`, `cf-promises`, `cf-runagent`, `cf-know`, `cf-report`, `cf-hub` + +Daemons include `cf-execd`, `cf-monitord`, and `cf-serverd` + +#### COSL license + +The Commercial Open Source License used for the CFEngine. -#### CMDB #### +#### Datatypes -A Configuration Management Database. A term coined as part of the IT Infrastructure Library (ITIL) as an outgrowth of an inventory database. +CFEngine's data types describe what a variable can contain. +A variable can't be assigned a different type once it's been set. +The commonly used data types are `string`, `slist` (string list), `int`, `real`, and `data`. -#### Commands #### -#### Common Control #### -#### Components #### +#### Diff -Standalone applications include cf-agent, cf-promises, cf-runagent, cf-know, cf-report, cf-hub +A `diff` is a report (originally that generated by the UNIX diff command) that details the differences between two files. +The term is often used as slang meaning a file comparison. -Daemons include cf-execd, cf-monitord, and cf-serverd +#### Enterprise API -#### Datatypes #### +The Enterprise API is a JSON HTTP REST API, allowing users to access CFEngine's functionality and reporting data programmatically. +It can be used to generate reports, query data, create alerts, manage users, etc. -CFEngine's data types describe what a variable can contain. A variable can't be assigned a different type once it's been set. The commonly used data types are `string`, `slist`, `int`, `real`, and `data`. +#### Enterprise reporting -#### Directories #### -#### Distribution #### -#### Enterprise API #### -#### Enterprise Reporting #### -#### File Structure #### -#### Frequency #### -#### Functions #### -#### Host #### +CFEngine's reporting system allows you to access information about your hosts and the results of your policy in a centralized system. +You can access the reporting system through the hub's JSON REST API, the Web UI, the SQL database, and generated PDF / CSV reports. -UNIX terminology for a computer the runs "guest programs." In practice, "host" is a synonym for "computer." +#### GPL3 -#### Hub #### +The GNU Public License, version 3. -A software component in CFEngine Enterprise that acts as a single point of management in a local "star-network." The term "hub" is sometimes used to mean policy distribution server, but more commonly a running cf-hub process that does report collection from all CFEngine managed hosts. The term hub means the centre of a wheel, from which multiple spokes emerge. +#### Graphical user interface (GUI) -#### Logs #### -#### Loops #### -#### Menus #### -#### Mission Portal #### -#### Monitoring #### -#### Namespaces #### -#### Networking #### -#### Normal Ordering #### -#### Operators #### -#### Pattern Matching #### +In contrast to text / command-line-based interfaces, GUIs use icons, images, color, spacing, and more complex layouts to improve the user experience. -#### PCI compliance #### +The CFEngine GUI is called Mission Portal and is accessible via a web browser. +It shows you useful information about your infrastructure and provides easy ways to make changes. + +#### Host + +UNIX terminology for a computer the runs _guest programs_. +In practice, _host_ is a synonym for _computer_. + +In CFEngine, all machines (physical or virtual) which have an installation of CFEngine are considered _hosts_. +We split them into 2 roles (categories) - hubs and clients. + +#### Hub + +The term hub means the center of a wheel, from which multiple spokes emerge. + +In CFEngine, the hub is the host responsible for collecting reports from hosts and serving them policy. +In addition to the components installed on other CFEngine hosts (clients), the hub runs a database (PostgreSQL), a web server (Apache) and a few additional CFEngine components, most notably `cf-hub`, which connects to hosts and retrieves their reporting data. + +Due to the multiple purposes this host serves, it is sometimes referred to as the policy server, the reporting hub, or the report collector. +In typical CFEngine Enterprise setups, all hubs are policy servers, and all policy servers are hubs, so the distinction is not so important. +In general, hub is the preferred term to describe the role of what this host does, and which package to install on it. + +See CFEngine role. + +#### Lightweight directory access protocol (LDAP) + +A kind of _phone book_ service providing information about persons and computers in an organization. + +#### Libraries + +A library generally refers to a collection of standardized CFEngine code that can be reused in different scenarios and environments. +This might be reusable bundles of promises, or bodies. + +#### Logs + +Log files tell you some historical, usually timestamped, information about events that happened in the past. +In CFEngine, there are a few notable log files: + +* `/var/logs/CFEngineInstall.log` - Information about the installation, especially useful if installing the package failed. +* `/var/cfengine/outputs/` - Output logs of previous scheduled agent runs (if any). +* `/var/cfengine/httpd/logs/error_log` - Apache errors (Mission Portal / API) + +#### Mission Portal (MP) + +Name of the user interface used in commercial CFEngine editions, where all reports and progress summaries are kept. + +#### Namespaces + +Namespaces allow you to define new scopes for bundles, variables, and classes. +By using a specific name for the namespace, you can use short and generic names for the identifiers inside of it. + +By default, if you don't specify a namespace, you are using the namespace called ```default```. +The CMDB (group data / host-specific data in Mission Portal) uses the ```data``` namespace unless you specify a namespace. + +You can think of namespaces in a similar way as putting files inside folders, instead of having all of your files in one folder. +The result is that things are more organized and less chances of files / classes / variables / bundles having conflicting names. + +#### Normal ordering + +In CFEngine, the promises you write in policy files are evaluated according to a predetermined order, not from top to bottom of your policy file. + +#### Packages + +Software binaries or executable files. +The CFEngine company compiles and tests software into packages suitable for different platforms. + +#### PCI compliance Payment Card Industry Data Security Standard (PCI DSS) is a set of requirements designed to ensure that ALL companies that process, store or transmit credit card information maintain a secure environment. -#### Policy Levels #### -#### Policy Server #### +#### Platforms + +This usually refers to an operating system type, e.g., Linux (in its many flavors), Windows, etc. +Platforms are described using short identifiers, e.g., RH5, REL5, SuSE 11, SLES, etc. -The special server that others consult for the latest policies is called the *Policy Server*. +#### Policy server + +The special server that others consult for the latest policies is called the *policy server*. Typically the policy server is set by the bootstrapping process. -#### Policy Writing #### -#### Policy #### +#### Policy + +A policy is a set of intentions about the system, coded as a list of promises. +A policy is not a standard, but the result of specific organizational management decisions. + +#### Promise attributes + +As opposed to the promiser string (which is usually the unique identifier of a resource), promise attributes specify the desired specifics for that resource. +A basic example is that if you want to ensure a file has a specific set of permissions, you would make a promise where the promiser string is the filename, and the desired permissions are specified as attributes. + +Sometimes referred to as promise constraints. -A policy is a set of intentions about the system, coded as a list of promises. A policy is not a standard, but the result of specific organizational management decisions. +#### Promise types -#### Precedence #### -#### Promise Attributes #### -#### Promise Types #### -#### Promise #### +Different types of resources you can manage with CFEngine. +Typical examples include files, users, services, packages, etc. +Making promises with these types results in CFEngine checking the state of those resources and making changes to the system if necessary. -The CFEngine software manages every intended system outcome as "promises" to be kept. A CFEngine Promise corresponds roughly to a rule in other software products, but importantly promises are always things that can be kept and repaired continuously, on a real time basis, not just once at install-time. +There are also promise types which are not traditional resources on a system, but rather just for managing state within the CFEngine binaries, such as variables, classes, meta, etc. +Setting a class or a variable will not alter the system directly, but makes that information available for further policy and promise types in the same execution. + +#### Promise + +The CFEngine software manages every intended system outcome as "promises" to be kept. +A CFEngine Promise corresponds roughly to a rule in other software products, but importantly promises are always things that can be kept and repaired continuously, on a real time basis, not just once at install-time. Promises are idempotent, meaning they can be executed many times with the same outcome. -They are also convergent, meaning they can only nudge the system closer to a steady state, never destabilize it. While there are ways a user could override this, it's almost never a good idea to do so. +They are also convergent, meaning they can only nudge the system closer to a steady state, never destabilize it. +While there are ways a user could override this, it's almost never a good idea to do so. + +#### Role based access control (RBAC) -#### Referencing #### -#### Report Collector #### -#### Reporting #### -#### Reports #### -#### Role-Based Access Control (RBAC) #### -#### Scope #### +RBAC allows you to control the level of access granted to individuals at a granular level. +Each user can have one or more roles, and each role can grant them access to specific resources and actions. +A flexible RBAC system improves the security of the system, especially when combined with a principle of least privilege approach. -#### Server #### +#### Server -For historical reasons, certain computers are referred to as servers, especially when kept in datacentres because such computers often run services. +For historical reasons, certain computers are referred to as servers, especially when kept in data centers because such computers often run services. -In CFEngine, cf-serverd is a software component that serves files from one computer to another. All computers are recommended to run cf-serverd, making all computers CFEngine servers, whether they are laptops, phones or datacentre computers. +In CFEngine, `cf-serverd` is a software component that serves files from one computer to another. +All computers are recommended to run `cf-serverd`, making all computers CFEngine servers, whether they are laptops, phones, or data center computers. The special server that others consult for the latest policies is called the Policy Server. -#### Special Variables #### -#### Standard Library #### +#### Service Catalogue + +A kind of directory of _services_ provided in an environment. +The concept of a service could be anything from a human help desk to a machine-controlled email subsystem. +In the CFEngine Mission Portal, the service catalog (for maintenance) treats promise bundles of promises as low-level maintenance services and relates these to high-level business goals. + +#### SOX Compliance + +Sarbanes-Oxley Act compliance. +An audited accolade for financial data security required by all companies on the New York Stock Exchange. + +#### Standard library + +The standard library lives in a `masterfiles/lib` subdirectory. +It's a collection of useful bundles and bodies you can use. + +#### Template + +A template usually refers to text that can be expanded based on the current CFEngine context. +CFEngine has a native template language, but generally, `mustache`, a logic-less templating language, is preferred. +Sometimes a template is an incomplete piece of CFEngine code, with blanks to fill in. +It is often a policy fragment that can be reused in different scenarios. +This is often used interchangeably with the term _library_. -The standard library lives in a `masterfiles/lib` subdirectory. It's a collection of useful bundles and bodies you can use. +#### Variables -#### Syntax #### -#### Variables #### -#### Version Control #### +Variables have a name, a type, and a value (and some optional metadata). +In CFEngine policy language, variables are similar to variables in other programming languages, they can hold strings, lists, complex data structures, etc. diff --git a/overview/how-cfengine-works.markdown b/overview/how-cfengine-works.markdown index a408670fa..9b1dec31e 100644 --- a/overview/how-cfengine-works.markdown +++ b/overview/how-cfengine-works.markdown @@ -3,29 +3,28 @@ layout: default title: How CFEngine works published: true sorting: 2 -tags: [getting started, faq] --- CFEngine is a fully distributed system that allows you to define desired states of everything from very large-scale infrastructures to small devices. The -lightweight c-based cf-agent runs locally on each resource and persistently +lightweight C-based `cf-agent` runs locally on each resource and persistently tries to converge towards the defined desired state. The actual states of managed resources are available in logs and an enterprise database for compliance and easy reporting. Using CFEngine, can be described in the following 3 simple steps. -## 1. Define Desired State +## 1. Define desired state As an end-user you can use the CFEngine Domain Specific Language (DSL) to define desired states. CFEngine allows you to define a variety of states ranging from process management to software deployment and file integrity. You can check out -CFEngine Promise Types to get an idea of the most common states you can define. +CFEngine Promise types to get an idea of the most common states you can define. Normally, all desired states are stored in `.cf` text-files in the `/var/cfengine/masterfiles` directory on one or more central distribution points, referred to as CFEngine Policy Hubs. -## 2. Ensure Actual State +## 2. Ensure actual state CFEngine typically runs locally on each managed resource. A resource can be anything from a server, network switch, raspberry pi, or any other computational @@ -34,11 +33,11 @@ evaluations occur on the local node. Before each run, which by default is every 5 minutes, the agent tries to connect to one of the Policy Hubs to check if there has been any policy updates. Upon -policy updates, cf-agent will download the latest policy to its own +policy updates, `cf-agent` will download the latest policy to its own `/var/cfengine/inputs` directory, run a syntax check and upon success start to execute. -## 3. Verify Actual State +## 3. Verify actual state Whenever the agent runs, it creates a log of local inventory, system states and execution results. The logs are stored in `/var/cfengine/outputs`. For enterprise @@ -58,7 +57,7 @@ agent was not able to restore into compliance https://www.youtube.com/watch?v=Zd9-wdGzedU {% endcomment %} ## Graphical illustration of CFEngine process - + ![Define -> Ensure -> Verify](how-does-cfengine-work-process.png) End-user and CFEngine agents workflow @@ -75,8 +74,9 @@ different platforms in many different environments including traditional servers, workstations and laptops, network gear (routers/switches), bus and tram systems, point of sales systems, smart displays/signs, and even submarines. -# Adopting CFEngine -## What does adoption involve? +## Adopting CFEngine + +### What does adoption involve? CFEngine is a framework and a methodology with far reaching implications for the way you do IT management. The CFEngine approach asks you to think in terms @@ -87,7 +87,7 @@ To use CFEngine effectively, you should spend a little time learning about the approach to management, as this will save you a lot of time and effort in the long run. -## The Mission Plan +### The Mission plan At CFEngine, we refer to the management of your datacentre as *The Mission*. The diagram below shows the main steps in preparing mission control. Some training @@ -101,7 +101,7 @@ Planning does not mean sitting around a table, or in front of a whiteboard. Successful planning is a dialogue between theory and practice. It should include test pilots and proof-of-concept implementations. -## Commercial or Free? +### Commercial or free? The first decision you should make is whether you will choose a route of commercial assistance or manage entirely on your own. You can choose different @@ -117,7 +117,7 @@ The advantages of the commercial products include greatly simplified set up procedures, continuous monitoring and automatic knowledge integration. See the CFEngine Nova Supplement for more information. -## Installation or Pilot +### Installation or pilot You are free to download Community Editions of CFEngine at any time to test the software. There is a considerable amount of documentation and example policy @@ -128,7 +128,7 @@ If you intend to purchase a significant number of commercial licenses for CFEngine software, you can request a pilot process, during which a specialist will install and demonstrate the commercial edition on site. -## Identifying the Team +### Identifying the team CFEngine will become a core discipline in your organization, taking you from reactive fire-fighting to proactive and strategic practices. You should invest @@ -144,13 +144,13 @@ All teams are important centres for knowledge, and you should provide incentives to keep the core team strong and in constant dialogue with your organization's strategic leadership. Treat your CFEngine team as a trusted partner in business. -## Training and Certification +### Training and certification Once you have tried the simplest examples using CFEngine, we recommend at least three days of in-depth training. We can also arrange more in-depth training to qualify as a CFEngine Mission Specialist. -## Mission Goal and Knowledge Management +### Mission goal and knowledge management The main aim of Knowledge Management is to learn from experience, and use the accumulated learning to improve the predictability of workflow processes. During @@ -180,14 +180,14 @@ can help you in this process, with training and Professional Services, but you must establish a culture of commitment to the mission and learn how to express these commitments in terms of CFEngine promises. -## Build, Deploy, Manage, Audit +### Build, deploy, manage, audit The four mission phases are sometimes referred to as * Build A mission is based on decisions and resources that need to be put assembled or - `built' before they can be applied. This is the planning phase. + `built` before they can be applied. This is the planning phase. In CFEngine, what you build is a template of proposed promises for the machines in an organization such that, if the machines all make and keep these @@ -198,7 +198,7 @@ The four mission phases are sometimes referred to as Deploying really means launching the policy into production. In CFEngine you simply publish your policy (in CFEngine parlance these are `promise - proposals') and the machines see the new proposals and can adjust + proposals`) and the machines see the new proposals and can adjust accordingly. Each machine runs an agent that is capable of keeping the system on course and maintaining it over time without further assistance. @@ -217,10 +217,10 @@ The four mission phases are sometimes referred to as examine these reports to check mission progress, or examine the current state in relation to the knowledge map for the mission. -[Contact CFEngine](mailto:contact@cfengine.com) +[Contact CFEngine](https://cfengine.com/contact) -# CFEngine Architecture and Design +## CFEngine architecture and design CFEngine operates autonomously in a network, under your guidance. While CFEngine supports anything from 1 servers to 100,000+ servers, the essence of any CFEngine deployment is the same. @@ -253,7 +253,7 @@ which are independent of external requirements. CFEngine works in all the places you think it should, and all the new places you haven't even thought of yet. -## Managing Expectations with Promises +### Managing expectations with promises CFEngine works on a simple notion of **promises**. A promise is the documentation of an intention to act or behave in some manner. When you make a @@ -281,7 +281,7 @@ managing machines and people. Combining promises with patterns to describe where and when promises should apply is what CFEngine is all about. -## Automation with CFEngine +### Automation with CFEngine Users are good at researching solutions and making design decisions, but awful at repeated execution. Machines are pitiful at making decisions, but very good @@ -301,42 +301,42 @@ operating systems, network topology or system processes. You describe the ideal state of a given system by creating promises and the CFEngine agents ensures that the necessary steps are taken to achieve this state. Automation in CFEngine is executed through a series of -[components][Overview#CFEngine Component Applications and Daemons] that run locally on hosts. +[components][Overview#CFEngine component applications and daemons] that run locally on hosts. -## Phases of System Management +### Phases of system management There are four commonly cited phases in managing systems with CFEngine: Build, Deploy, Manage, and Audit. -### Build +#### Build A system is based on a number of decisions and resources that need to be -`built' before they can be implemented. You don't need to decide every detail, +`built` before they can be implemented. You don't need to decide every detail, just enough to build trust and predictability into your system. In CFEngine, what you build is a template of proposed promises for the machines being -managed. If the machines in a system all make and keep these promises, the +managed. If the machines in a system all make and keep these promises, the system will function seamlessly as planned. -### Deploy +#### Deploy Deploying really means implementing the policy that was already decided. In transaction systems, one tries to push out changes one-by-one, hence -`deploying' the decision. In CFEngine you simply publish your policy (in +`deploying` the decision. In CFEngine you simply publish your policy (in CFEngine parlance these are "promise proposals") and the machines see the new proposals and can adjust accordingly. Each machine runs an agent that is capable of implementing policies and maintaining them over time without further assistance. -### Manage +#### Manage Once a decision is made, unplanned events will occur. Such incidents traditionally set off alarms and humans rush to make new transactions to -repair them. In CFEngine, the autonomous agent manages the system, and you +repair them. In CFEngine, the autonomous agent manages the system, and you only have to deal with rare events that cannot be dealt with automatically. This is the key difference of CFEngine, a focus on autonomy and creating agents that are smart enough to adapt to changing situations. -### Audit +#### Audit In traditional configuration systems, the outcome is far from clear after a one-shot transaction, so one audits the system to determine what actually @@ -355,4 +355,4 @@ direction). All of the desired-state changes are managed locally by each individual host, and continuously repaired to ensure on-going compliance with policy. -See Also: [Client server communication][Client server communication] +See also: [Client server communication][Client server communication] diff --git a/overview/what-is-cfengine-and-why.markdown b/overview/what-is-cfengine-and-why.markdown index 68b47188a..276e08459 100644 --- a/overview/what-is-cfengine-and-why.markdown +++ b/overview/what-is-cfengine-and-why.markdown @@ -1,9 +1,8 @@ --- layout: default -title: What is CFEngine and Why? +title: What is CFEngine and why? published: true sorting: 1 -tags: [getting started, faq] --- ## What is CFEngine? diff --git a/redirects.conf b/redirects.conf index 23393f5e8..579956c0b 100644 --- a/redirects.conf +++ b/redirects.conf @@ -5,9 +5,3 @@ # vhost instance. Version specific docs are simply sub-directories. As such, # rewrites here apply to all versions of docs and must account for the correct # doc version in the path. - - -# Redirect moved getting started guide -RewriteRule ^/docs/master/guide-getting-started-with-cfengine-build.html$ /docs/master/getting-started-getting-started-with-cfengine-build.html [R] - -RewriteRule ^/nickanderson https://www.linkedin.com/in/hithisisnick/ \ No newline at end of file diff --git a/reference.markdown b/reference.markdown index bd6a1d1c6..53fddde73 100644 --- a/reference.markdown +++ b/reference.markdown @@ -12,14 +12,14 @@ Language elements that belong together are typically documented on the same page. * [Components][Components] -* [Promise Types][Promise Types] +* [Promise types][Promise types] * [Functions][Functions] -* [Language Concepts][Language Concepts] -* [Special Variables][Special Variables] -* [Enterprise API Reference][Enterprise API Reference] -* [Syntax, identifiers and names][Language Concepts#Syntax, identifiers and names] +* [Language concepts][Language concepts] +* [Special variables][Special variables] +* [Enterprise API reference][Enterprise API reference] +* [Syntax, identifiers and names][Language concepts#Syntax, identifiers and names] * [Masterfiles Policy Framework][Masterfiles Policy Framework] -* [All Promise and Body Types][All Promise and Body Types] +* [All promise and body types][All promise and body types] * [Macros][Macros] -See Also: [All Promise Types][All Promise and Body Types#All Promise Types], [All Body Types][All Promise and Body Types#All Body Types] +See also: [All promise types][All promise and body types#All promise types], [All body Types][All promise and body types#All body Types] diff --git a/reference/all-types.markdown b/reference/all-types.markdown index 4cd1f105e..5f4fc616f 100644 --- a/reference/all-types.markdown +++ b/reference/all-types.markdown @@ -1,18 +1,17 @@ --- layout: default -title: All Promise and Body Types +title: All promise and body types published: true sorting: 110 -tags: [reference] --- -* [All Promise Types][All Promise and Body Types#All Promise Types] -* [All Body Types][All Promise and Body Types#All Body Types] +* [All promise types][All promise and body types#All promise types] +* [All body Types][All promise and body types#All body Types] -## All Promise Types +## All promise types [%CFEngine_syntax_map(promiseTypes)] -## All Body Types +## All body Types [%CFEngine_syntax_map(bodyTypes)] diff --git a/reference/common-attributes-include.markdown b/reference/common-attributes-include.markdown index 968a73d8b..309623820 100644 --- a/reference/common-attributes-include.markdown +++ b/reference/common-attributes-include.markdown @@ -1,23 +1,25 @@ -### Common Attributes +### Common attributes Common attributes are available to all promise types. Full details for common -attributes can be found in the [Common Promise Attributes section][Promise Types#Common Promise Attributes] of -the [Promise Types] page. The common attributes are as follows: +attributes can be found in the [Common promise attributes section][Promise types#Common promise attributes] of +the [Promise types] page. The common attributes are as follows: -#### [action][Promise Types#action] +#### [action][Promise types#action] -#### [classes][Promise Types#classes] +#### [classes][Promise types#classes] -#### [comment][Promise Types#comment] +#### [comment][Promise types#comment] -#### [depends_on][Promise Types#depends_on] +#### [depends_on][Promise types#depends_on] -#### [handle][Promise Types#handle] +#### [handle][Promise types#handle] -#### [if][Promise Types#if] +#### [if][Promise types#if] -#### [meta][Promise Types#meta] +#### [unless][Promise types#unless] -#### [with][Promise Types#with] +#### [meta][Promise types#meta] + +#### [with][Promise types#with]
      diff --git a/reference/common-body-attributes-include.markdown b/reference/common-body-attributes-include.markdown index 7dabe368e..2db1963e0 100644 --- a/reference/common-body-attributes-include.markdown +++ b/reference/common-body-attributes-include.markdown @@ -1,13 +1,13 @@ -#### Common Body Attributes +#### Common body attributes Common body attributes are available to all body types. Full details for common body attributes can be found in the -[Common Body Attributes section][Promise Types#Common Body Attributes] -of the [Promise Types] page. The common attributes are as +[Common body attributes section][Promise types#Common body attributes] +of the [Promise types] page. The common attributes are as follows: -##### [inherit_from][Promise Types#inherit_from] +##### [inherit_from][Promise types#inherit_from] -##### [meta][Promise Types#meta] +##### [meta][Promise types#meta]
      diff --git a/reference/components.markdown b/reference/components.markdown index 81e1ef2bf..c30dd4780 100644 --- a/reference/components.markdown +++ b/reference/components.markdown @@ -3,7 +3,6 @@ layout: default title: Components published: true sorting: 10 -tags: [Reference, Components] --- While promises to configure your system are entirely user-defined, the @@ -14,12 +13,12 @@ defined in bodies because the actual promises are fixed and you only change their details within sensible limits. See the -[introduction][Overview#CFEngine Component Applications and Daemons] +[introduction][Overview#CFEngine component applications and daemons] for a high-level overview of the CFEngine components, and each component's reference documentation for the details about the specific control bodies. -## Common Control +## Common control The `common` control body refers to those promises that are hard-coded into all the components of CFEngine, and therefore @@ -193,7 +192,7 @@ runs of e.g. `cf-agent` and `cf-promises`. cache_system_functions => "true"; ``` -**See also:** [`ifelapsed` in action bodies][Promise Types#ifelapsed] +**See also:** [`ifelapsed` in action bodies][Promise types#ifelapsed] **History:** - Introduced in version 3.6.0. @@ -581,7 +580,7 @@ body common control ### tls_ciphers -**Description:** List of ciphers allowed when making **outgoing** connections. +**Description:** List of ciphers allowed when making **outgoing** connections from components other than `cf-serverd`. For a list of possible ciphers, see man page for "openssl ciphers". @@ -603,7 +602,7 @@ body common control ### tls_min_version -**Description:** Minimum tls version to allow for **outgoing** connections. +**Description:** Minimum tls version to allow for **outgoing** connections from components other than `cf-serverd`. [%CFEngine_promise_attribute(1.0)%] diff --git a/reference/components/cf-agent.markdown b/reference/components/cf-agent.markdown index d95ef8730..291b8a9c9 100644 --- a/reference/components/cf-agent.markdown +++ b/reference/components/cf-agent.markdown @@ -3,13 +3,12 @@ layout: default title: cf-agent published: true sorting: 10 -tags: [Components, cf-agent] keywords: [agent] --- `cf-agent` evaluates policy code and makes changes to the system. Policy bundles are evaluated in the order of the provided `bundlesequence` (this is normally specified in the -[`common control body`][Components#Common Control]). For +[`common control body`][Components#Common control]). For each bundle, `cf-agent` groups promise statements according to their type. Promise types are then evaluated in a preset order to ensure fast system convergence to policy. @@ -25,7 +24,53 @@ affected by `common` and `agent` control bodies. [%CFEngine_include_snippet(cf-agent.help, [\s]*--[a-z], ^$)%] -## Automatic Bootstrapping +### --simulate + +Like the `--dry-run` option, the `--simulate` option tries to identify changes +to your system without making changes to the system, however it goes further +than `--dry-run` by making changes in a `chroot` and making a distinction +between *safe* and *unsafe* functions, e.g. `execresult()`. + +The agent will execute promises with unsafe functions when the `--simulate` +options is given only if the promise using the function is tagged `simulate_safe`. + +For example: + +```cf3 +bundle agent __main__ +{ + vars: + "msg" + string => execresult( "/bin/echo Hello world!", "useshell" ), + meta => { "simulate_safe" }; +} +``` + +The simulate option takes a parameter, `diff`, `manifest`, or `manifest-full` +which is used to determine the summary output shown at the end of the run. + +* `diff` - Show only things that changed during the simulated run. +* `manifest` - Show files and packages changed by the simulated run. +* `manifest-full` - Show all files evaluated by the simulated run (including unchanged ones) + + - cf-agent can now simulate the changes done to files in a chroot, printing + diff or manifest information about what it would do in a normal evaluation. + Use the new command line option: `--simulate=diff` or `--simulate=manifest`. + Please note that only files and packages promises are simulated currently. + + - Added a new --simulate=manifest-full mode + New simulation mode that manifests all changed files as well as + all other files evaluated by the agent run which were not skipped + (by file selection rules) (CFE-3506) + +#### Notes +* Supported on Linux for `files` and `packages` type promises + +#### History +* Introduced in version 3.17.0 +* `--simulate=manifest-full` introduced in version 3.18.0 + +## Automatic bootstrapping Automatic bootstrapping allows the user to connect a CFEngine Host to a Policy Server without specifying the IP address manually. It uses the *Avahi* service @@ -39,8 +84,8 @@ following Avahi libraries: To make the CFEngine Server discoverable, it needs to register itself as an Avahi service. Run the following command: -``` -$ /var/cfengine/bin/cf-serverd -A +```command +/var/cfengine/bin/cf-serverd -A ``` This generates the configuration file for Avahi in `/etc/avahi/services` and @@ -50,8 +95,8 @@ From this point on, the Policy Server will be discovered with the Avahi service. To verify that the server is visible, run the following command (requires `avahi-utils`): -``` -$ avahi-browse -atr | grep cfenginehub +```command +avahi-browse -atr | grep cfenginehub ``` The sample output looks like this: @@ -64,8 +109,8 @@ _cfenginehub._tcp local Once the Policy Server is configured with the Avahi service, you can auto-bootstrap Hosts to it. -``` -$ /var/cfengine/bin/cf-agent -B :avahi +```command +/var/cfengine/bin/cf-agent -B :avahi ``` The Hosts require Avahi libraries to be installed in order to use this @@ -74,8 +119,8 @@ locations. Install locations vary from system to system. If Avahi is installed in a non-standard location (i.e. compiled from source), set the `AVAHI_PATH` environmental variable to specify the path. -``` -$ AVAHI_PATH=/lib/libavahi-client.so.3 /var/cfengine/bin/cf-agent -B +```command +AVAHI_PATH=/lib/libavahi-client.so.3 /var/cfengine/bin/cf-agent -B ``` If more than one server is found, or if the server has more than one IP @@ -83,8 +128,8 @@ address, the list of all available servers is printed and the user is asked to manually specify the IP address of the correct server by running the standard bootstrap command of cf-agent: -``` -$ /var/cfengine/bin/cf-agent --bootstrap +```command +/var/cfengine/bin/cf-agent --bootstrap ``` If only one Policy Server is found in the network, `cf-agent` performs the @@ -93,7 +138,7 @@ bootstrap without further manual user intervention. **Note:** Automatic bootstrapping support is ONLY for Linux, and it is limited only to one subnet. -## Control Promises +## Control promises Settings describing the details of the fixed behavioral promises made by `cf-agent`. @@ -102,21 +147,17 @@ made by `cf-agent`. body agent control { # Agent email report settings based on their domain. - - alpha_cfengine_com:: - domain => "alpha.cfengine.com"; - mailto => "admins@alpha.cfengine.com"; - - beta_domain_com:: - domain => "beta.cfengine.com"; - mailto => "admins@beta.cfengine.com"; - - any:: - mailfrom => "root"; + alpha_cfengine_com:: + domain => "alpha.cfengine.com"; + mailto => "admins@alpha.cfengine.com"; + beta_domain_com:: + domain => "beta.cfengine.com"; + mailto => "admins@beta.cfengine.com"; + any:: + mailfrom => "root"; } ``` - ### abortbundleclasses **Description:** The `abortbundleclasses` slist contains regular expressions @@ -137,57 +178,47 @@ method bundle. ```cf3 body common control - { -bundlesequence => { "testbundle" }; -version => "1.2.3"; + bundlesequence => { "testbundle" }; + version => "1.2.3"; } ################################# body agent control - { -abortbundleclasses => { "invalid.*" }; + abortbundleclasses => { "invalid.*" }; } ################################# bundle agent testbundle { -vars: - - "userlist" slist => { "xyz", "mark", "jeang", "jonhenrik", "thomas", "eben" }; - -methods: - - "any" usebundle => subtest("$(userlist)"); - + vars: + "userlist" + slist => { "xyz", "mark", "jeang", "jonhenrik", "thomas", "eben" }; + methods: + "any" + usebundle => subtest("$(userlist)"); } ################################# bundle agent subtest(user) - { -classes: - - "invalid" not => regcmp("[a-z]{4}","$(user)"); - -reports: - - !invalid:: - - "User name $(user) is valid at exactly 4 letters"; - - # abortbundleclasses will prevent this from being evaluated - invalid:: - - "User name $(user) is invalid"; + classes: + "invalid" + not => regcmp("[a-z]{4}","$(user)"); + reports: + !invalid:: + "User name $(user) is valid at exactly 4 letters"; + + # abortbundleclasses will prevent this from being evaluated + invalid:: + "User name $(user) is invalid"; } ``` - ### abortclasses **Description:** The `abortclasses` slist contains regular expressions that @@ -209,6 +240,7 @@ body agent control { abortclasses => { "danger.*", "should_not_continue" }; } + bundle agent main { methods: @@ -216,6 +248,7 @@ bundle agent main "bundle_b"; "bundle_c"; } + bundle agent bundle_a { classes: @@ -233,10 +266,8 @@ bundle common bundle_b bundle agent bundle_c { classes: - # Here we define a class that will match the abortclasses under more complex # conditions - "should_not_continue" expression => "(abort_condition_a.abort_condition_b).!something_else", scope => "namespace"; @@ -283,7 +314,6 @@ Classes here are added unequivocally to the system. If classes are used to predicate definition, then they must be defined in terms of global hard classes. - ### agentaccess **Description:** A `agentaccess` slist contains user names that are @@ -353,7 +383,7 @@ during agent execution. ```cf3 body agent control { -allclassesreport => "true"; + allclassesreport => "true"; } ``` @@ -378,11 +408,9 @@ executing, or only after updates. ```cf3 body agent control { -Min00_05:: - - # revalidate once per hour, regardless of change in configuration - - alwaysvalidate => "true"; + Min00_05:: + # revalidate once per hour, regardless of change in configuration + alwaysvalidate => "true"; } ``` @@ -396,7 +424,6 @@ will force a revalidation of the input. **History:** Was introduced in version 3.1.2,Enterprise 2.0.1 (2010) - ### auditing **Deprecated:** This menu option policy is deprecated, does @@ -445,7 +472,7 @@ class. ```cf3 body agent control { -checksum_alert_time => "30"; + checksum_alert_time => "30"; } ``` @@ -466,11 +493,10 @@ of the agent. ```cf3 body agent control { -childlibpath => "/usr/local/lib:/usr/local/gnu/lib"; + childlibpath => "/usr/local/lib:/usr/local/gnu/lib"; } ``` - ### copyfrom_restrict_keys This attribute restricts `cf-agent` to copying files from hosts that have a key explicitly defined in this list. @@ -478,13 +504,16 @@ This attribute restricts `cf-agent` to copying files from hosts that have a key **Example:** ```cf3 -body agent control { - copyfrom_restrict_keys => { "SHA=6565a8e647e61e4a7ff2c709e0fe772acce2e45aaa294b2bb713de0ba5a6d8c3", - "SHA=727dd7f6f8b2344c6d69cf1d3ed0446c0f9f095ce1a114481d691bf1cb2b300d" +body agent control +{ + copyfrom_restrict_keys => { + "SHA=6565a8e647e61e4a7ff2c709e0fe772acce2e45aaa294b2bb713de0ba5a6d8c3", + "SHA=727dd7f6f8b2344c6d69cf1d3ed0446c0f9f095ce1a114481d691bf1cb2b300d", + } } ``` -**See Also:** `admit_keys`, `controls/cf_agent.cf` +**See also:** `admit_keys`, `controls/cf_agent.cf` **History:** * Introduced in 3.20.0 @@ -511,7 +540,7 @@ repository. ```cf3 body agent control { -default_repository => "/var/cfengine/repository"; + default_repository => "/var/cfengine/repository"; } ``` @@ -550,7 +579,6 @@ body agent control * `cf-serverd` will time out any transfer that takes longer than 10 minutes (this is not currently tunable). - ### defaultcopytype **Description:** The `defaultcopytype` menu option policy sets the global @@ -572,12 +600,11 @@ default policy for comparing source and image in copy transactions. ```cf3 body agent control { -#... -defaultcopytype => "digest"; + #... + defaultcopytype => "digest"; } ``` - ### dryrun **Description:** The `dryrun` menu option, if set, makes no changes to @@ -592,11 +619,10 @@ the system, and will only report what it needs to do. ```cf3 body agent control { -dryrun => "true"; + dryrun => "true"; } ``` - ### editbinaryfilesize **Description:** The value of `editbinaryfilesize` represents the limit @@ -616,7 +642,7 @@ and may be overridden on a per-promise basis with `max_file_size`. ```cf3 body agent control { -edibinaryfilesize => "10M"; + edibinaryfilesize => "10M"; } ``` @@ -643,7 +669,7 @@ overridden on a per-promise basis with `max_file_size`. ```cf3 body agent control { -editfilesize => "120k"; + editfilesize => "120k"; } ``` @@ -664,19 +690,18 @@ The values of environment variables are inherited by child commands. ```cf3 body common control { -bundlesequence => { "one" }; + bundlesequence => { "one" }; } body agent control { -environment => { "A=123", "B=456", "PGK_PATH=/tmp"}; + environment => { "A=123", "B=456", "PGK_PATH=/tmp"}; } bundle agent one { -commands: - - "/usr/bin/env"; + commands: + "/usr/bin/env"; } ``` @@ -685,10 +710,9 @@ Some interactive programs insist on values being set, for example: ```cf3 # Required by apt-cache, debian -environment => { "LANG=C"}; +environment => { "LANG=C" }; ``` - ### expireafter **Description:** The value of `expireafter` is a global default for time @@ -708,12 +732,12 @@ kill and restart its attempt to keep a promise. ```cf3 body action example { -ifelapsed => "120"; # 2 hours -expireafter => "240"; # 4 hours + ifelapsed => "120"; # 2 hours + expireafter => "240"; # 4 hours } ``` -**See also:** [`body action expireafter`][Promise Types#expireafter], [`body contain exec_timeout`][commands#exec_timeout], [`body executor control agent_expireafter`][cf-execd#agent_expireafter] +**See also:** [`body action expireafter`][Promise types#expireafter], [`body contain exec_timeout`][commands#exec_timeout], [`body executor control agent_expireafter`][cf-execd#agent_expireafter] ### files_auto_define @@ -757,7 +781,7 @@ for lazy-evaluation of overlapping file-copy promises. ```cf3 body agent control { -files_single_copy => { "/etc/.*", "/special/file" }; + files_single_copy => { "/etc/.*", "/special/file" }; } ``` @@ -779,11 +803,10 @@ etc) this is a common setting. ```cf3 body agent control { -hashupdates => "true"; + hashupdates => "true"; } ``` - ### hostnamekeys **Deprecated:** Host identification is now handled transparently. @@ -804,7 +827,7 @@ addresses. ```cf3 body server control { -hostnamekeys => "true"; + hostnamekeys => "true"; } ``` @@ -834,19 +857,26 @@ another which is not tied to a specific time. body action example { -ifelapsed => "120"; # 2 hours -expireafter => "240"; # 4 hours + ifelapsed => "120"; # 2 hours + expireafter => "240"; # 4 hours } # global body agent control { -ifelapsed => "180"; # 3 hours + ifelapsed => "180"; # 3 hours } ``` -**See also:** [Promise locking][Promises#Promise Locking], [ifelapsed action body attribute][Promise Types#ifelapsed] +**Notes:** + +* A value of `0` means no locking, all promises will be executed each execution if in context. This also disables function caching. +* This is not a reliable way to control frequency over a long period of time. +* Locks provide simple but weak frequency control. +* Locks older than 4 weeks are automatically purged. + +**See also:** [Promise locking][Promises#Promise locking], [ifelapsed action body attribute][Promise types#ifelapsed] ### inform @@ -865,7 +895,7 @@ It is equivalent to (and when present, overrides) the command line option ```cf3 body agent control { -inform => "true"; + inform => "true"; } ``` @@ -878,7 +908,6 @@ compatibility. **Default value:** false - ### max_children **Description:** The value of `max_children` represents the maximum number @@ -902,11 +931,11 @@ diminishing returns. ```cf3 body agent control { -max_children => "10"; + max_children => "10"; } ``` -**See also:** [`background` in action bodies][Promise Types#background] +**See also:** [`background` in action bodies][Promise types#background] ### maxconnections @@ -926,7 +955,7 @@ number of outgoing connections to `cf-serverd`. body agent control { -maxconnections => "1000"; + maxconnections => "1000"; } ``` @@ -935,7 +964,6 @@ maxconnections => "1000"; Watch out for kernel limitations for maximum numbers of open file descriptors which can limit this. - ### mountfilesystems **Description:** The `mountfilesystems` menu option policy determines @@ -953,7 +981,7 @@ file system table. ```cf3 body agent control { -mountfilesystems => "true"; + mountfilesystems => "true"; } ``` @@ -973,7 +1001,7 @@ This test is applied in all recursive/depth searches. ```cf3 body agent control { -nonalphanumfiles => "true"; + nonalphanumfiles => "true"; } ``` @@ -998,8 +1026,8 @@ at the start of every scheduled bundle. ```cf3 body agent control { -refresh_processes => { "mybundle" }; -#refresh_processes => { "none" }; + refresh_processes => { "mybundle" }; + # refresh_processes => { "none" }; } ``` @@ -1026,7 +1054,7 @@ canonize pathnames in the file repository. ```cf3 body agent control { -repchar => "_"; + repchar => "_"; } ``` @@ -1078,6 +1106,7 @@ The following classes are excluded from logging: * `any` * `from_cfexecd` * Life cycle (`Lcycle_0`, `GMT_Lcycle_3`) + ### secureinput **Description:** The `secureinput` menu option policy checks whether @@ -1095,7 +1124,7 @@ owned by a privileged user. ```cf3 body agent control { -secureinput => "true"; + secureinput => "true"; } ``` @@ -1139,7 +1168,7 @@ number of files a mounted filesystem is expected to have. ```cf3 body agent control { -sensiblecount => "20"; + sensiblecount => "20"; } ``` @@ -1159,11 +1188,10 @@ number of bytes a mounted filesystem is expected to have. ```cf3 body agent control { -sensiblesize => "20K"; + sensiblesize => "20K"; } ``` - ### skipidentify **Description:** The `skipidentify` menu option policy determines whether @@ -1184,7 +1212,7 @@ credentials. ```cf3 body agent control { -skipidentify => "true"; + skipidentify => "true"; } ``` @@ -1205,7 +1233,7 @@ it will skip them and output a warning message. ```cf3 body agent control { -suspiciousnames => { ".mo", "lrk3", "rootkit" }; + suspiciousnames => { ".mo", "lrk3", "rootkit" }; } ``` @@ -1228,11 +1256,10 @@ machine must comply with. ```cf3 body agent control { -timezone => { "MET", "CET", "GMT+1" }; + timezone => { "MET", "CET", "GMT+1" }; } ``` - ### track_value **Deprecated:** This menu option policy is deprecated as of 3.6.0. It performs @@ -1256,6 +1283,6 @@ promise. ```cf3 body agent control { -verbose => "true"; + verbose => "true"; } ``` diff --git a/reference/components/cf-check.markdown b/reference/components/cf-check.markdown index 7a2fc61b7..6a9f701d2 100644 --- a/reference/components/cf-check.markdown +++ b/reference/components/cf-check.markdown @@ -3,7 +3,6 @@ layout: default title: cf-check published: true sorting: 80 -tags: [reference, components, cf-check] keywords: [cf-hub] --- diff --git a/reference/components/cf-execd.markdown b/reference/components/cf-execd.markdown index 8fef60f54..e9c7b58bf 100644 --- a/reference/components/cf-execd.markdown +++ b/reference/components/cf-execd.markdown @@ -3,7 +3,6 @@ layout: default title: cf-execd published: true sorting: 30 -tags: [Components, cf-execd] keywords: [executor] --- @@ -32,7 +31,7 @@ network. [%CFEngine_include_snippet(cf-execd.help, [\s]*--[a-z], ^$)%] -## Control Promises +## Control promises These body settings determine the behavior of `cf-execd`,including scheduling times and output capture to `WORKDIR/outputs` and relay via email. @@ -44,7 +43,7 @@ body executor control mailto => "cfengine@example.org"; mailfrom => "cfengine@$(host).example.org"; smtpserver => "localhost"; - schedule => { "Min00_05", "Min30_35" } + schedule => { "Min00", "Min30" } } ``` @@ -86,7 +85,7 @@ set it to `120` and you are using a 5-minute agent schedule, a maximum of 120 / 5 = 24 agents should be enforced. -**See also:** [`body action expireafter`][Promise Types#expireafter], [`body contain exec_timeout`][commands#exec_timeout], [`body agent control expireafter`][cf-agent#expireafter] +**See also:** [`body action expireafter`][Promise types#expireafter], [`body contain exec_timeout`][commands#exec_timeout], [`body agent control expireafter`][cf-agent#expireafter] ### executorfacility @@ -309,7 +308,7 @@ function may be affected by changing the `schedule`. ```cf3 body executor control { -schedule => { "Min00", "(Evening|Night).Min15_20", "Min30", "(Evening|Night).Min45_50" }; +schedule => { "Min00", "(Evening|Night).Min15", "Min30", "(Evening|Night).Min45" }; } ``` diff --git a/reference/components/cf-hub.markdown b/reference/components/cf-hub.markdown index d908d085e..5b23945a9 100644 --- a/reference/components/cf-hub.markdown +++ b/reference/components/cf-hub.markdown @@ -3,7 +3,6 @@ layout: default title: cf-hub published: true sorting: 80 -tags: [reference, components, cf-hub, enterprise] keywords: [hub] --- @@ -29,7 +28,7 @@ avoid reporting on data generated by test or extraordinary executions. [%CFEngine_include_snippet(cf-hub.help, [\s]*--[a-z], ^$)%] -## Control Promises +## Control promises ```cf3 body hub control @@ -82,9 +81,9 @@ body hub control { # Collect reports every at the top and half of the hour. Additionally collect - # reports during the evening or night between Minute 45 and 50. + # reports during the evening or night at Minute 45. - hub_schedule => { "Min00", "Min30", "(Evening|Night).Min45_50" }; + hub_schedule => { "Min00", "Min30", "(Evening|Night).Min45" }; } ``` diff --git a/reference/components/cf-key.markdown b/reference/components/cf-key.markdown index 52c79d157..a2383ed6b 100644 --- a/reference/components/cf-key.markdown +++ b/reference/components/cf-key.markdown @@ -3,7 +3,6 @@ layout: default title: cf-key published: true sorting: 60 -tags: [Components, cf-key] --- The CFEngine key generator makes key pairs for [remote authentication][Client server communication]. diff --git a/reference/components/cf-monitord.markdown b/reference/components/cf-monitord.markdown index 3682a45ec..ea0ca43c3 100644 --- a/reference/components/cf-monitord.markdown +++ b/reference/components/cf-monitord.markdown @@ -3,7 +3,6 @@ layout: default title: cf-monitord published: true sorting: 50 -tags: [Components, cf-monitord] keywords: [monitor] --- @@ -133,7 +132,7 @@ Note: There is no way for force a refresh of the monitored data. * `cf_state.lmdb` * `history.lmdb` -## Statistical Classes +## Statistical classes `cf-monitord` automatically defines classes based on the observation of the data is has collected. Classes defined are named for the measurement id (the promise @@ -157,7 +156,7 @@ The following prefixes may be used when defining classes: Note: These suffixes and prefixes may be combined, resulting in a class like `rootprocs_high`, `loadavg_high_ldt`, `cpu1_high_dev3`, and `entropy_postgresql_out_low`. -## Control Promises +## Control promises Settings describing the details of the fixed behavioral promises made by `cf-monitord`. The system defaults will be sufficient for diff --git a/reference/components/cf-net.markdown b/reference/components/cf-net.markdown index 00ce6502d..ee9eb7bac 100644 --- a/reference/components/cf-net.markdown +++ b/reference/components/cf-net.markdown @@ -3,7 +3,6 @@ layout: default title: cf-net published: true sorting: 90 -tags: [Components, cf-net] keywords: [protocol, cli] --- diff --git a/reference/components/cf-promises.markdown b/reference/components/cf-promises.markdown index 20f7ac096..0e72750d3 100644 --- a/reference/components/cf-promises.markdown +++ b/reference/components/cf-promises.markdown @@ -3,7 +3,6 @@ layout: default title: cf-promises published: true sorting: 40 -tags: [Components, cf-promises] --- `cf-promises` is a tool for checking CFEngine policy code. It operates by diff --git a/reference/components/cf-reactor.markdown b/reference/components/cf-reactor.markdown index fd90ef6a1..fc3860aee 100644 --- a/reference/components/cf-reactor.markdown +++ b/reference/components/cf-reactor.markdown @@ -2,7 +2,6 @@ layout: default title: cf-reactor published: true -tags: [Components, cf-reactor, Enterprise] keywords: [reactor] --- diff --git a/reference/components/cf-runagent.markdown b/reference/components/cf-runagent.markdown index 03f5ff8ee..5502045f6 100644 --- a/reference/components/cf-runagent.markdown +++ b/reference/components/cf-runagent.markdown @@ -3,17 +3,21 @@ layout: default title: cf-runagent published: true sorting: 70 -tags: [Components, cf-runagent] keywords: [runagent] --- `cf-runagent` connects to a list of running instances of `cf-serverd`. It allows foregoing the usual `cf-execd` schedule to activate `cf-agent`. -Additionally, a user may send [classes][Classes and Decisions] to be defined +A user may send [classes][Classes and decisions] to be defined on the remote host. Two kinds of classes may be sent: classes to decide on which hosts `cf-agent` will be started, and classes that the user requests `cf-agent` should define on execution. The latter type is regulated by `cf-serverd`'s [role based access control][roles]. +Additionally a user may send a list of [bundles][Bundles] to activate on the remote host +with the `--remote-bundles` argument. +This argument takes one or more comma separated bundle names. +Each of the bundles requested must be given explicit permission with an access promise +matching the bundle names. **Notes:** @@ -25,7 +29,7 @@ which hosts `cf-agent` will be started, and classes that the user requests **See also:** [bundle resource_type in server access promises][access#resource_type], [cfruncommand in body server control][cf-serverd#cfruncommand] -## Control Promises +## Control promises Settings describing the details of the fixed behavioral promises made by `cf-runagent`. The most important parameter here is the list of hosts that the diff --git a/reference/components/cf-secret.markdown b/reference/components/cf-secret.markdown index 7554862b8..1a7416d40 100644 --- a/reference/components/cf-secret.markdown +++ b/reference/components/cf-secret.markdown @@ -3,7 +3,6 @@ layout: default title: cf-secret published: true sorting: 10 -tags: [Components, cf-secret] keywords: [cf-secret] --- diff --git a/reference/components/cf-serverd.markdown b/reference/components/cf-serverd.markdown index eb191c41a..46b3909e0 100644 --- a/reference/components/cf-serverd.markdown +++ b/reference/components/cf-serverd.markdown @@ -3,7 +3,6 @@ layout: default title: cf-serverd published: true sorting: 20 -tags: [Components, cf-serverd] keywords: [server] --- @@ -23,6 +22,8 @@ affected by `common` and `server` control bodies. * This daemon reloads it's config when the SIGHUP signal is received. * If `enable_report_dumps` exists in `WORKDIR` (`/var/cfengine/enable_report_dumps`) `cf-serverd` will log reports provided to `cf-hub` to `WORKDIR/diagnostics/report_dump` (`/var/cfengine/diagnostics/report_dumps`). This data is useful when troubleshooting reporting issues with CFEngine Enterprise. * `cf-serverd` always considers the class ```server``` to be defined. +* `SIGUSR1` sets the log level to debug. +* `SIGUSR2` sets the log level to notice. **History:** @@ -33,7 +34,7 @@ affected by `common` and `server` control bodies. [%CFEngine_include_snippet(cf-serverd.help, [\s]*--[a-z], ^$)%] -## Control Promises +## Control promises Settings describing the details of the fixed behavioral promises made by `cf-serverd`. Server controls are mainly about determining access policy for @@ -144,7 +145,7 @@ specify a list of hosts allowed to use the legacy protocol. ### allowciphers -**Description:** List of TLS ciphers the server accepts for **incoming** connections. +**Description:** List of TLS ciphers the server accepts both **incoming** and **outgoing** (in the case of client initiated reporting with CFEngine Enterprise) connections using `cf-serverd`. For a list of possible ciphers, see man page for "openssl ciphers". [%CFEngine_promise_attribute(AES256-GCM-SHA384:AES256-SHA)%] @@ -177,7 +178,7 @@ this does not do anything as the classic protocol does not support TLS ciphers. ### allowtlsversion -**Description:** Minimum TLS version allowed for **incoming** connections. +**Description:** Minimum TLS version allowed for both **incoming** and **outgoing** (in the case of client initiated reporting with CFEngine Enterprise) connections using `cf-serverd`. [%CFEngine_promise_attribute(1.0)%] diff --git a/reference/components/file_control_promises.markdown b/reference/components/file_control_promises.markdown index 2d1f4127c..e62066c44 100644 --- a/reference/components/file_control_promises.markdown +++ b/reference/components/file_control_promises.markdown @@ -3,7 +3,6 @@ layout: default title: file control published: true sorting: 100 -tags: [body, bodies, components, common, namespace, promises, bundlesequence] --- @@ -24,7 +23,7 @@ bundle agent private This directive can be given multiple times within any file, outside of body and bundle definitions. -Only [soft classes][Classes and Decisions] from common bundles can +Only [soft classes][Classes and decisions] from common bundles can be used in class decisions inside `file control bodies`. ### inputs diff --git a/reference/functions.markdown b/reference/functions.markdown index 6b8299dcf..594bb520f 100644 --- a/reference/functions.markdown +++ b/reference/functions.markdown @@ -3,7 +3,6 @@ layout: default title: Functions published: true sorting: 30 -tags: [Reference, Functions] --- Functions take zero or more values as arguments and return a value. @@ -57,7 +56,7 @@ bundle agent main **Note:** the truth of a class expression or the result of a function call may change during evaluation, but typically, a class, once defined, will stay defined. -**See also:** [persistence in classes and decisions][Classes and Decisions#persistence] +**See also:** [persistence in classes and decisions][Classes and decisions#persistence] ### Promise attributes and function calls @@ -112,11 +111,11 @@ When enabled [cached functions](https://docs.cfengine.com/docs/{{site.cfengine.branch}}/search.html?q=The+return+value+is+cached) are **not executed on every pass of convergence**. Instead, the function will only be executed once during the -[agent evaluation step][Normal Ordering#Agent evaluation step] +[agent evaluation step][Normal ordering#Agent evaluation step] and its result will be cached until the end of that agent execution. **Note:** Cached functions are executed multiple times during -[policy validation and pre-evaluation][Normal Ordering#cf-promises policy validation step]. +[policy validation and pre-evaluation][Normal ordering#cf-promises policy validation step]. Function caching is *per-process*, so results will not be cached between separate components e.g. `cf-agent`, `cf-serverd` and `cf-promises`. Additionally functions are cached by hashing the function arguments. If you have @@ -127,10 +126,10 @@ occurrences. Function caching can be globally disabled by setting `cache_system_functions` in body common control to `false` or locally for a specific promise by using -`ifelapsed => "0"` in the [action body][Promise Types#ifelapsed] +`ifelapsed => "0"` in the [action body][Promise types#ifelapsed] of the promise. -## Function Skipping +## Function skipping If a variable passed to a function is unable to be resolved the function will be skipped. The function will be evaluated during a later pass when all diff --git a/reference/functions/accessedbefore.markdown b/reference/functions/accessedbefore.markdown index d3a963422..31ae665ed 100644 --- a/reference/functions/accessedbefore.markdown +++ b/reference/functions/accessedbefore.markdown @@ -2,7 +2,6 @@ layout: default title: accessedbefore published: true -tags: [reference, files functions, functions, accessedbefore] --- [%CFEngine_function_prototype(newer,older)%] diff --git a/reference/functions/accumulated.markdown b/reference/functions/accumulated.markdown index fc207b20b..2608386cf 100644 --- a/reference/functions/accumulated.markdown +++ b/reference/functions/accumulated.markdown @@ -2,7 +2,6 @@ layout: default title: accumulated published: true -tags: [reference, data functions, functions, accumulated] --- [%CFEngine_function_prototype(years, months, days, hours, minutes, seconds)%] diff --git a/reference/functions/ago.markdown b/reference/functions/ago.markdown index 1a21f0c8c..e98835827 100644 --- a/reference/functions/ago.markdown +++ b/reference/functions/ago.markdown @@ -2,7 +2,6 @@ layout: default title: ago published: true -tags: [reference, data functions, functions, ago] --- [%CFEngine_function_prototype(years, months, days, hours, minutes, seconds)%] diff --git a/reference/functions/and.markdown b/reference/functions/and.markdown index 0d431d370..affbdcc28 100644 --- a/reference/functions/and.markdown +++ b/reference/functions/and.markdown @@ -2,7 +2,6 @@ layout: default title: and published: true -tags: [reference, data functions, functions, and] --- [%CFEngine_function_prototype(...)%] diff --git a/reference/functions/basename.markdown b/reference/functions/basename.markdown index a72ba7e5d..6c03fd669 100644 --- a/reference/functions/basename.markdown +++ b/reference/functions/basename.markdown @@ -2,7 +2,6 @@ layout: default title: basename published: true -tags: [reference, functions, basename] --- [%CFEngine_function_prototype(filename, optional_extension)%] diff --git a/reference/functions/bundlesmatching.markdown b/reference/functions/bundlesmatching.markdown index 1b1f96e5d..8f351048d 100644 --- a/reference/functions/bundlesmatching.markdown +++ b/reference/functions/bundlesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: bundlesmatching published: true -tags: [reference, utility functions, functions, bundlesmatching] --- [%CFEngine_function_prototype(name, tag1, tag2, ...)%] diff --git a/reference/functions/bundlestate.markdown b/reference/functions/bundlestate.markdown index cc1473be0..bdb2b442c 100644 --- a/reference/functions/bundlestate.markdown +++ b/reference/functions/bundlestate.markdown @@ -2,7 +2,6 @@ layout: default title: bundlestate published: true -tags: [reference, data functions, functions, json, bundlestate, evaluation, vars, classes, container] --- [%CFEngine_function_prototype(bundlename)%] diff --git a/reference/functions/callstack_callers.markdown b/reference/functions/callstack_callers.markdown index b6f72478f..f7a4fdecc 100644 --- a/reference/functions/callstack_callers.markdown +++ b/reference/functions/callstack_callers.markdown @@ -2,7 +2,6 @@ layout: default title: callstack_callers published: true -tags: [reference, internal functions, functions, callstack_callers, call, stack, debugging] --- [%CFEngine_function_prototype()%] diff --git a/reference/functions/callstack_promisers.markdown b/reference/functions/callstack_promisers.markdown index e36e8b23d..0c8d1d71b 100644 --- a/reference/functions/callstack_promisers.markdown +++ b/reference/functions/callstack_promisers.markdown @@ -2,7 +2,6 @@ layout: default title: callstack_promisers published: true -tags: [reference, internal functions, functions, callstack_promisers, call, stack, promisers, debugging] --- [%CFEngine_function_prototype()%] diff --git a/reference/functions/canonify.markdown b/reference/functions/canonify.markdown index 6ffb3bc9b..af19a74a0 100644 --- a/reference/functions/canonify.markdown +++ b/reference/functions/canonify.markdown @@ -2,7 +2,6 @@ layout: default title: canonify published: true -tags: [reference, data functions, functions, canonify] --- [%CFEngine_function_prototype(text)%] diff --git a/reference/functions/canonifyuniquely.markdown b/reference/functions/canonifyuniquely.markdown index e356b422f..f0b464f48 100644 --- a/reference/functions/canonifyuniquely.markdown +++ b/reference/functions/canonifyuniquely.markdown @@ -2,7 +2,6 @@ layout: default title: canonifyuniquely published: true -tags: [reference, data functions, functions, canonify, canonifyuniquely, hash] --- [%CFEngine_function_prototype(text)%] diff --git a/reference/functions/cf_version_after.markdown b/reference/functions/cf_version_after.markdown index 1b2a876aa..4ccc76811 100644 --- a/reference/functions/cf_version_after.markdown +++ b/reference/functions/cf_version_after.markdown @@ -2,7 +2,6 @@ layout: default title: cf_version_after published: true -tags: [reference, utility functions, functions] --- [%CFEngine_function_prototype(string)%] diff --git a/reference/functions/cf_version_at.markdown b/reference/functions/cf_version_at.markdown index cd4234b13..e19cd190f 100644 --- a/reference/functions/cf_version_at.markdown +++ b/reference/functions/cf_version_at.markdown @@ -2,7 +2,6 @@ layout: default title: cf_version_at published: true -tags: [reference, utility functions, functions] --- [%CFEngine_function_prototype(string)%] diff --git a/reference/functions/cf_version_before.markdown b/reference/functions/cf_version_before.markdown index 449d671c6..f480f7779 100644 --- a/reference/functions/cf_version_before.markdown +++ b/reference/functions/cf_version_before.markdown @@ -2,7 +2,6 @@ layout: default title: cf_version_before published: true -tags: [reference, utility functions, functions] --- [%CFEngine_function_prototype(string)%] diff --git a/reference/functions/cf_version_between.markdown b/reference/functions/cf_version_between.markdown index c7c50745a..e1852017d 100644 --- a/reference/functions/cf_version_between.markdown +++ b/reference/functions/cf_version_between.markdown @@ -2,7 +2,6 @@ layout: default title: cf_version_between published: true -tags: [reference, utility functions, functions] --- [%CFEngine_function_prototype(string, string)%] diff --git a/reference/functions/cf_version_maximum.markdown b/reference/functions/cf_version_maximum.markdown index 5e2299a6e..582ebdc27 100644 --- a/reference/functions/cf_version_maximum.markdown +++ b/reference/functions/cf_version_maximum.markdown @@ -2,7 +2,6 @@ layout: default title: cf_version_maximum published: true -tags: [reference, utility functions, functions] --- [%CFEngine_function_prototype(string)%] diff --git a/reference/functions/cf_version_minimum.markdown b/reference/functions/cf_version_minimum.markdown index 2c34af399..1eb7c31be 100644 --- a/reference/functions/cf_version_minimum.markdown +++ b/reference/functions/cf_version_minimum.markdown @@ -2,7 +2,6 @@ layout: default title: cf_version_minimum published: true -tags: [reference, utility functions, functions] --- [%CFEngine_function_prototype(string)%] diff --git a/reference/functions/changedbefore.markdown b/reference/functions/changedbefore.markdown index 5f96d2295..ccc7787e0 100644 --- a/reference/functions/changedbefore.markdown +++ b/reference/functions/changedbefore.markdown @@ -2,7 +2,6 @@ layout: default title: changedbefore published: true -tags: [reference, files functions, functions, changedbefore] --- [%CFEngine_function_prototype(newer,older)%] diff --git a/reference/functions/classesmatching.markdown b/reference/functions/classesmatching.markdown index c5387bcb6..acc24582e 100644 --- a/reference/functions/classesmatching.markdown +++ b/reference/functions/classesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: classesmatching published: true -tags: [reference, utility functions, functions, classesmatching] --- [%CFEngine_function_prototype(name, tag1, tag2, ...)%] @@ -17,7 +16,9 @@ classes. The search order is hard, soft, then local to the current bundle. When any tags are given, only the classes with those tags matching the given [anchored][anchored] regular expressions are returned. Class tags are set -using the [`meta`][Promise Types#meta] attribute. +using the [`meta`][Promise types#meta] attribute. + +If no classes match `name` and any tags given then an empty list is returned. [%CFEngine_function_attributes(name, tag1, tag2, ...)%] diff --git a/reference/functions/classfiltercsv.markdown b/reference/functions/classfiltercsv.markdown index 4aaea10de..c3f779f7f 100644 --- a/reference/functions/classfiltercsv.markdown +++ b/reference/functions/classfiltercsv.markdown @@ -2,7 +2,6 @@ layout: default title: classfiltercsv published: true -tags: [reference, csv, data functions, functions, classfiltercsv] --- [%CFEngine_function_prototype(filename, has_header, class_column, optional_sort_column)%] diff --git a/reference/functions/classify.markdown b/reference/functions/classify.markdown index 16dc0bd56..cf0e5a181 100644 --- a/reference/functions/classify.markdown +++ b/reference/functions/classify.markdown @@ -2,7 +2,6 @@ layout: default title: classify published: true -tags: [reference, data functions, functions, classify] --- [%CFEngine_function_prototype(text)%] diff --git a/reference/functions/classmatch.markdown b/reference/functions/classmatch.markdown index 231970d45..c1b65d6f0 100644 --- a/reference/functions/classmatch.markdown +++ b/reference/functions/classmatch.markdown @@ -2,7 +2,6 @@ layout: default title: classmatch published: true -tags: [reference, utility functions, functions, classmatch] --- [%CFEngine_function_prototype(regex, tag1, tag2, ...)%] diff --git a/reference/functions/concat.markdown b/reference/functions/concat.markdown index 4503b2bff..00f750987 100644 --- a/reference/functions/concat.markdown +++ b/reference/functions/concat.markdown @@ -2,7 +2,6 @@ layout: default title: concat published: true -tags: [reference, data functions, functions, concat] --- [%CFEngine_function_prototype(...)%] diff --git a/reference/functions/countclassesmatching.markdown b/reference/functions/countclassesmatching.markdown index c583ebc23..beb543f01 100644 --- a/reference/functions/countclassesmatching.markdown +++ b/reference/functions/countclassesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: countclassesmatching published: true -tags: [reference, utility functions, functions, countclassesmatching] --- [%CFEngine_function_prototype(regex, tag1, tag2, ...)%] diff --git a/reference/functions/countlinesmatching.markdown b/reference/functions/countlinesmatching.markdown index 2c3c42de9..e76fa7d63 100644 --- a/reference/functions/countlinesmatching.markdown +++ b/reference/functions/countlinesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: countlinesmatching published: true -tags: [reference, io functions, functions, countlinesmatching] --- [%CFEngine_function_prototype(regex, filename)%] diff --git a/reference/functions/data_expand.markdown b/reference/functions/data_expand.markdown index 9154f09df..9ac4672f1 100644 --- a/reference/functions/data_expand.markdown +++ b/reference/functions/data_expand.markdown @@ -2,7 +2,6 @@ layout: default title: data_expand published: true -tags: [reference, data functions, functions, json, container, expand, inline_json] --- [%CFEngine_function_prototype(data_container)%] diff --git a/reference/functions/data_readstringarray.markdown b/reference/functions/data_readstringarray.markdown index 1180bc271..9b4e6ab5d 100644 --- a/reference/functions/data_readstringarray.markdown +++ b/reference/functions/data_readstringarray.markdown @@ -2,7 +2,6 @@ layout: default title: data_readstringarray published: true -tags: [reference, io functions, functions, data_readstringarray] --- [%CFEngine_function_prototype(filename, comment, split, maxentries, maxbytes)%] diff --git a/reference/functions/data_readstringarrayidx.markdown b/reference/functions/data_readstringarrayidx.markdown index 9996c9851..0bf11579c 100644 --- a/reference/functions/data_readstringarrayidx.markdown +++ b/reference/functions/data_readstringarrayidx.markdown @@ -2,7 +2,6 @@ layout: default title: data_readstringarrayidx published: true -tags: [reference, io functions, functions, data_readstringarrayidx] --- [%CFEngine_function_prototype(filename, comment, split, maxentries, maxbytes)%] diff --git a/reference/functions/data_regextract.markdown b/reference/functions/data_regextract.markdown index 9aa3011bc..d5b518f4f 100644 --- a/reference/functions/data_regextract.markdown +++ b/reference/functions/data_regextract.markdown @@ -2,7 +2,6 @@ layout: default title: data_regextract published: true -tags: [reference, data functions, functions, json, container, regextract, pcre] --- [%CFEngine_function_prototype(regex, string)%] diff --git a/reference/functions/data_sysctlvalues.markdown b/reference/functions/data_sysctlvalues.markdown index fe7c525f2..736fa28f8 100644 --- a/reference/functions/data_sysctlvalues.markdown +++ b/reference/functions/data_sysctlvalues.markdown @@ -2,7 +2,6 @@ layout: default title: data_sysctlvalues published: true -tags: [reference, system functions, functions, sysctl, data_sysctlvalues] --- [%CFEngine_function_prototype()%] diff --git a/reference/functions/datastate.markdown b/reference/functions/datastate.markdown index 16fbc8383..38dde8711 100644 --- a/reference/functions/datastate.markdown +++ b/reference/functions/datastate.markdown @@ -2,7 +2,6 @@ layout: default title: datastate published: true -tags: [reference, data functions, functions, json, datastate, evaluation, vars, classes, container] --- [%CFEngine_function_prototype()%] diff --git a/reference/functions/difference.markdown b/reference/functions/difference.markdown index 50992469d..6af4ab44d 100644 --- a/reference/functions/difference.markdown +++ b/reference/functions/difference.markdown @@ -2,7 +2,6 @@ layout: default title: difference published: true -tags: [reference, data functions, functions, difference, inline_json] --- [%CFEngine_function_prototype(list1, list2)%] diff --git a/reference/functions/dirname.markdown b/reference/functions/dirname.markdown index 572989937..1a7635886 100644 --- a/reference/functions/dirname.markdown +++ b/reference/functions/dirname.markdown @@ -2,7 +2,6 @@ layout: default title: dirname published: true -tags: [reference, files functions, functions, dirname] --- [%CFEngine_function_prototype(path)%] diff --git a/reference/functions/diskfree.markdown b/reference/functions/diskfree.markdown index 1aa2f58b1..c14effa2d 100644 --- a/reference/functions/diskfree.markdown +++ b/reference/functions/diskfree.markdown @@ -2,7 +2,6 @@ layout: default title: diskfree published: true -tags: [reference, files functions, functions, diskfree] --- [%CFEngine_function_prototype(path)%] diff --git a/reference/functions/escape.markdown b/reference/functions/escape.markdown index 21a418bb9..e96e21cc8 100644 --- a/reference/functions/escape.markdown +++ b/reference/functions/escape.markdown @@ -2,7 +2,6 @@ layout: default title: escape published: true -tags: [reference, data functions, functions, escape] --- [%CFEngine_function_prototype(text)%] diff --git a/reference/functions/eval.markdown b/reference/functions/eval.markdown index a65676863..63f94fdb3 100644 --- a/reference/functions/eval.markdown +++ b/reference/functions/eval.markdown @@ -2,7 +2,6 @@ layout: default title: eval published: true -tags: [reference, data functions, functions, eval, context, class, equality, numbers] --- [%CFEngine_function_prototype(expression, mode, options)%] diff --git a/reference/functions/every.markdown b/reference/functions/every.markdown index 9bb2bf875..319866411 100644 --- a/reference/functions/every.markdown +++ b/reference/functions/every.markdown @@ -2,7 +2,6 @@ layout: default title: every published: true -tags: [reference, data functions, functions, every, inline_json] --- [%CFEngine_function_prototype(regex, list)%] diff --git a/reference/functions/execresult.markdown b/reference/functions/execresult.markdown index 2bb397b45..7e01e06e6 100644 --- a/reference/functions/execresult.markdown +++ b/reference/functions/execresult.markdown @@ -2,7 +2,6 @@ layout: default title: execresult published: true -tags: [reference, utility functions, functions, execresult, cached function] --- [%CFEngine_function_prototype(command, shell, output)%] diff --git a/reference/functions/execresult_as_data.markdown b/reference/functions/execresult_as_data.markdown index a19cccaca..11cb09052 100644 --- a/reference/functions/execresult_as_data.markdown +++ b/reference/functions/execresult_as_data.markdown @@ -2,7 +2,6 @@ layout: default title: execresult_as_data published: true -tags: [reference, utility functions, functions, execresult_as_data, cached function] --- [%CFEngine_function_prototype(command, shell, output)%] diff --git a/reference/functions/expandrange.markdown b/reference/functions/expandrange.markdown index b564c6136..3924eba67 100644 --- a/reference/functions/expandrange.markdown +++ b/reference/functions/expandrange.markdown @@ -2,7 +2,6 @@ layout: default title: expandrange published: true -tags: [reference, files functions, functions, expandrange] --- [%CFEngine_function_prototype(string_template, stepsize)%] diff --git a/reference/functions/file_hash.markdown b/reference/functions/file_hash.markdown index 7d046f120..6c2aea30b 100644 --- a/reference/functions/file_hash.markdown +++ b/reference/functions/file_hash.markdown @@ -2,7 +2,6 @@ layout: default title: file_hash published: true -tags: [reference, data functions, functions, hash] --- [%CFEngine_function_prototype(file, algorithm)%] diff --git a/reference/functions/fileexists.markdown b/reference/functions/fileexists.markdown index 8af69d85e..02bd2881b 100644 --- a/reference/functions/fileexists.markdown +++ b/reference/functions/fileexists.markdown @@ -2,7 +2,6 @@ layout: default title: fileexists published: true -tags: [reference, files functions, functions, fileexists] --- [%CFEngine_function_prototype(filename)%] diff --git a/reference/functions/filesexist.markdown b/reference/functions/filesexist.markdown index 9c79a2359..7e50f88e6 100644 --- a/reference/functions/filesexist.markdown +++ b/reference/functions/filesexist.markdown @@ -2,7 +2,6 @@ layout: default title: filesexist published: true -tags: [reference, files functions, functions, filesexist] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/filesize.markdown b/reference/functions/filesize.markdown index 5f69d547f..12a3b99d6 100644 --- a/reference/functions/filesize.markdown +++ b/reference/functions/filesize.markdown @@ -2,7 +2,6 @@ layout: default title: filesize published: true -tags: [reference, files functions, functions, filesize] --- [%CFEngine_function_prototype(filename)%] diff --git a/reference/functions/filestat.markdown b/reference/functions/filestat.markdown index 99352237e..984bf33ce 100644 --- a/reference/functions/filestat.markdown +++ b/reference/functions/filestat.markdown @@ -2,7 +2,6 @@ layout: default title: filestat published: true -tags: [reference, files functions, functions, filestat] --- [%CFEngine_function_prototype(filename, field)%] diff --git a/reference/functions/filter.markdown b/reference/functions/filter.markdown index 47108ffe0..b9ce3719b 100644 --- a/reference/functions/filter.markdown +++ b/reference/functions/filter.markdown @@ -2,7 +2,6 @@ layout: default title: filter published: true -tags: [reference, data functions, functions, filter, inline_json] --- [%CFEngine_function_prototype(filter, list, is_regex, invert, max_return)%] diff --git a/reference/functions/findfiles.markdown b/reference/functions/findfiles.markdown index b057ca8ba..348c50f4a 100644 --- a/reference/functions/findfiles.markdown +++ b/reference/functions/findfiles.markdown @@ -2,7 +2,6 @@ layout: default title: findfiles published: true -tags: [reference, file functions, functions, findfiles, files, glob] --- [%CFEngine_function_prototype(glob1, glob2, ...)%] @@ -23,6 +22,13 @@ deep. This function, used together with the `bundlesmatching` function, allows you to do dynamic inputs and a dynamic bundle call chain. +**WARNING:** +- The current implementation of glob patterns on Windows contains bugs. + Therefore, we strongly recommend using the `!windows::` class guard + expression to safeguard against any use of the function on Windows platforms. + Rest assured, we are actively working on resolving these issues and improving + its functionality. + **Notes:** - Brace expansion is not currently supported, `{x,y,anything}` will not match `x` or `y` or `anything`. diff --git a/reference/functions/findfiles_up.markdown b/reference/functions/findfiles_up.markdown index 5e9401f89..6b5c81616 100644 --- a/reference/functions/findfiles_up.markdown +++ b/reference/functions/findfiles_up.markdown @@ -2,7 +2,6 @@ layout: default title: findfiles_up published: true -tags: [reference, file functions, functions, findfiles_up, files, glob] --- [%CFEngine_function_prototype(path, glob, level)%] @@ -14,9 +13,9 @@ This function searches for files matching a given glob pattern `glob` in the local filesystem by searching up the directory tree from a given absolute path `path`. The function searches at moast `level` levels of directories or until the root directory is reached. Argument `level` defaults to `inf` if -not specified. The function returnes a list of files as a data array where +not specified. The function returns a list of files as a data array where the first element _(element 0)_ and the last element _(element N)_ is first -and last file or directory found respectivly. +and last file or directory found respectively. Note that glob patterns are not regular expressions. They match like Unix shells: @@ -25,6 +24,13 @@ shells: * `?` matches a single letter * `[a-z]` matches any letter from `a` to `z` +**WARNING:** +- The current implementation of glob patterns on Windows contains bugs. + Therefore, we strongly recommend using the `!windows::` class guard + expression to safeguard against any use of the function on Windows platforms. + Rest assured, we are actively working on resolving these issues and improving + its functionality. + **Notes:** - Brace expansion is not currently supported, `{x,y,anything}` will not match `x` or `y` or `anything`. diff --git a/reference/functions/findprocesses.markdown b/reference/functions/findprocesses.markdown index 0cb92efe7..634e26b78 100644 --- a/reference/functions/findprocesses.markdown +++ b/reference/functions/findprocesses.markdown @@ -2,7 +2,6 @@ layout: default title: findprocesses published: true -tags: [reference, process functions, functions, findprocesses, process, processes, ps, cached function] --- [%CFEngine_function_prototype(regex)%] diff --git a/reference/functions/format.markdown b/reference/functions/format.markdown index 4d0ece96a..63f032550 100644 --- a/reference/functions/format.markdown +++ b/reference/functions/format.markdown @@ -2,7 +2,6 @@ layout: default title: format published: true -tags: [reference, data functions, functions, format] --- [%CFEngine_function_prototype(string, ...)%] diff --git a/reference/functions/getclassmetatags.markdown b/reference/functions/getclassmetatags.markdown index 7f84ff862..24874b3d2 100644 --- a/reference/functions/getclassmetatags.markdown +++ b/reference/functions/getclassmetatags.markdown @@ -2,12 +2,11 @@ layout: default title: getclassmetatags published: true -tags: [reference, data functions, functions, getclassmetatags, meta, tags] --- [%CFEngine_function_prototype(classname, optional_tag)%] -**Description:** Returns the list of [`meta`][Promise Types#meta] tags for class `classname`. +**Description:** Returns the list of [`meta`][Promise types#meta] tags for class `classname`. [%CFEngine_function_attributes(classname, optional_tag)%] diff --git a/reference/functions/getenv.markdown b/reference/functions/getenv.markdown index 3b615033a..2f191e228 100644 --- a/reference/functions/getenv.markdown +++ b/reference/functions/getenv.markdown @@ -2,7 +2,6 @@ layout: default title: getenv published: true -tags: [reference, system functions, functions, getenv] --- [%CFEngine_function_prototype(variable, maxlength)%] diff --git a/reference/functions/getfields.markdown b/reference/functions/getfields.markdown index 6f513983c..b280219f6 100644 --- a/reference/functions/getfields.markdown +++ b/reference/functions/getfields.markdown @@ -2,7 +2,6 @@ layout: default title: getfields published: true -tags: [reference, data functions, functions, getfields] --- [%CFEngine_function_prototype(regex, filename, split, array_lval)%] diff --git a/reference/functions/getgid.markdown b/reference/functions/getgid.markdown index dd6870808..dc67a88e6 100644 --- a/reference/functions/getgid.markdown +++ b/reference/functions/getgid.markdown @@ -2,7 +2,6 @@ layout: default title: getgid published: true -tags: [reference, data functions, functions, getgid] --- [%CFEngine_function_prototype(groupname)%] diff --git a/reference/functions/getindices.markdown b/reference/functions/getindices.markdown index 45bd241a1..c42166c93 100644 --- a/reference/functions/getindices.markdown +++ b/reference/functions/getindices.markdown @@ -2,7 +2,6 @@ layout: default title: getindices published: true -tags: [reference, data functions, functions, getindices, inline_json] --- [%CFEngine_function_prototype(varref)%] diff --git a/reference/functions/getuid.markdown b/reference/functions/getuid.markdown index ad4fbf3de..e3197d102 100644 --- a/reference/functions/getuid.markdown +++ b/reference/functions/getuid.markdown @@ -2,7 +2,6 @@ layout: default title: getuid published: true -tags: [reference, system functions, functions, getuid] --- [%CFEngine_function_prototype(username)%] diff --git a/reference/functions/getuserinfo.markdown b/reference/functions/getuserinfo.markdown index 5656a973a..c362868cc 100644 --- a/reference/functions/getuserinfo.markdown +++ b/reference/functions/getuserinfo.markdown @@ -2,7 +2,6 @@ layout: default title: getuserinfo published: true -tags: [reference, user functions, functions, getuserinfo, users, uid, gid, gecos, homedir, shell] --- [%CFEngine_function_prototype(optional_uidorname)%] diff --git a/reference/functions/getusers.markdown b/reference/functions/getusers.markdown index 9b3ec767d..efe4a631c 100644 --- a/reference/functions/getusers.markdown +++ b/reference/functions/getusers.markdown @@ -2,12 +2,11 @@ layout: default title: getusers published: true -tags: [reference, system functions, functions, getusers] --- [%CFEngine_function_prototype(exclude_names, exclude_ids)%] -**Description:** Returns a list of all users defined, except those names in `exclude_names` and uids in `exclude_ids` +**Description:** Returns a list of all users defined, except those names in the comma separated string of `exclude_names` and the comma separated string of uids in `exclude_ids` [%CFEngine_function_attributes(exclude_names, exclude_ids)%] diff --git a/reference/functions/getvalues.markdown b/reference/functions/getvalues.markdown index a0e1ff6ef..c915fa1cc 100644 --- a/reference/functions/getvalues.markdown +++ b/reference/functions/getvalues.markdown @@ -2,7 +2,6 @@ layout: default title: getvalues published: true -tags: [reference, data functions, functions, getvalues, inline_json] --- [%CFEngine_function_prototype(varref)%] diff --git a/reference/functions/getvariablemetatags.markdown b/reference/functions/getvariablemetatags.markdown index 590fdbcbc..eea8a8bf4 100644 --- a/reference/functions/getvariablemetatags.markdown +++ b/reference/functions/getvariablemetatags.markdown @@ -2,12 +2,11 @@ layout: default title: getvariablemetatags published: true -tags: [reference, data functions, functions, getvariablemetatags, meta, tags] --- [%CFEngine_function_prototype(varname, optional_tag)%] -**Description:** Returns the list of [`meta`][Promise Types#meta] tags for variable `varname`. +**Description:** Returns the list of [`meta`][Promise types#meta] tags for variable `varname`. Make sure you specify the correct scope when supplying the name of the variable. diff --git a/reference/functions/grep.markdown b/reference/functions/grep.markdown index 8e5a707cf..997cb2f31 100644 --- a/reference/functions/grep.markdown +++ b/reference/functions/grep.markdown @@ -2,7 +2,6 @@ layout: default title: grep published: true -tags: [reference, data functions, functions, grep, inline_json] --- [%CFEngine_function_prototype(regex, list)%] diff --git a/reference/functions/groupexists.markdown b/reference/functions/groupexists.markdown index eaa0a742f..be90dd9bd 100644 --- a/reference/functions/groupexists.markdown +++ b/reference/functions/groupexists.markdown @@ -2,7 +2,6 @@ layout: default title: groupexists published: true -tags: [reference, system functions, functions, groupexists] --- [%CFEngine_function_prototype(group)%] diff --git a/reference/functions/hash.markdown b/reference/functions/hash.markdown index 5cea23329..03726d336 100644 --- a/reference/functions/hash.markdown +++ b/reference/functions/hash.markdown @@ -2,7 +2,6 @@ layout: default title: hash published: true -tags: [reference, data functions, functions, hash] --- [%CFEngine_function_prototype(input, algorithm)%] diff --git a/reference/functions/hash_to_int.markdown b/reference/functions/hash_to_int.markdown index 7f057964e..38df46de8 100644 --- a/reference/functions/hash_to_int.markdown +++ b/reference/functions/hash_to_int.markdown @@ -2,7 +2,6 @@ layout: default title: hash_to_int published: true -tags: [reference, functions, hash_to_int, function_returns_int] --- [%CFEngine_function_prototype( lower, upper, string )%] diff --git a/reference/functions/hashmatch.markdown b/reference/functions/hashmatch.markdown index 840f60bcf..0c0a47ed7 100644 --- a/reference/functions/hashmatch.markdown +++ b/reference/functions/hashmatch.markdown @@ -2,7 +2,6 @@ layout: default title: hashmatch published: true -tags: [reference, data functions, functions, hashmatch] --- [%CFEngine_function_prototype(filename, algorithm, hash)%] diff --git a/reference/functions/host2ip.markdown b/reference/functions/host2ip.markdown index 4a4fbb76e..a4a6a2c1b 100644 --- a/reference/functions/host2ip.markdown +++ b/reference/functions/host2ip.markdown @@ -2,7 +2,6 @@ layout: default title: host2ip published: true -tags: [reference, communication functions, functions, host2ip, cached function] --- [%CFEngine_function_prototype(hostname)%] diff --git a/reference/functions/hostinnetgroup.markdown b/reference/functions/hostinnetgroup.markdown index 16572670b..7dbc11430 100644 --- a/reference/functions/hostinnetgroup.markdown +++ b/reference/functions/hostinnetgroup.markdown @@ -2,7 +2,6 @@ layout: default title: hostinnetgroup published: true -tags: [reference, system functions, functions, hostinnetgroup] --- [%CFEngine_function_prototype(netgroup)%] diff --git a/reference/functions/hostrange.markdown b/reference/functions/hostrange.markdown index 6edaa48c3..0a3ddc36f 100644 --- a/reference/functions/hostrange.markdown +++ b/reference/functions/hostrange.markdown @@ -2,7 +2,6 @@ layout: default title: hostrange published: true -tags: [reference, communication functions, functions, hostrange] --- [%CFEngine_function_prototype(prefix, range)%] diff --git a/reference/functions/hostsseen.markdown b/reference/functions/hostsseen.markdown index a643ca7e4..ce7975b30 100644 --- a/reference/functions/hostsseen.markdown +++ b/reference/functions/hostsseen.markdown @@ -2,7 +2,6 @@ layout: default title: hostsseen published: true -tags: [reference, communication functions, functions, hostsseen] --- [%CFEngine_function_prototype(horizon, seen, field)%] diff --git a/reference/functions/hostswithclass.markdown b/reference/functions/hostswithclass.markdown index 52a106ac4..fe2d1173c 100644 --- a/reference/functions/hostswithclass.markdown +++ b/reference/functions/hostswithclass.markdown @@ -2,7 +2,6 @@ layout: default title: hostswithclass published: true -tags: [reference, communication functions, functions, hostswithclass] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/hubknowledge.markdown b/reference/functions/hubknowledge.markdown index 90f9db97d..c0ed841f4 100644 --- a/reference/functions/hubknowledge.markdown +++ b/reference/functions/hubknowledge.markdown @@ -2,7 +2,6 @@ layout: default title: hubknowledge published: true -tags: [reference, communication functions, functions, hubknowledge, cached function] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/ifelse.markdown b/reference/functions/ifelse.markdown index 63b6a082d..59885cced 100644 --- a/reference/functions/ifelse.markdown +++ b/reference/functions/ifelse.markdown @@ -2,7 +2,6 @@ layout: default title: ifelse published: true -tags: [reference, data functions, functions, ifelse] --- [%CFEngine_function_prototype(...)%] diff --git a/reference/functions/int.markdown b/reference/functions/int.markdown index 2c8e4f514..ed6425439 100644 --- a/reference/functions/int.markdown +++ b/reference/functions/int.markdown @@ -2,7 +2,6 @@ layout: default title: int published: true -tags: [reference, functions, int] --- [%CFEngine_function_prototype(string)%] @@ -17,7 +16,7 @@ If `string` represents a floating point number then the decimals are *truncated* [%CFEngine_include_example(int.cf)%] -**See Also:** [`string()`][string] +**See also:** [`string()`][string] **History:** diff --git a/reference/functions/intersection.markdown b/reference/functions/intersection.markdown index c72490961..6eb53db4d 100644 --- a/reference/functions/intersection.markdown +++ b/reference/functions/intersection.markdown @@ -2,7 +2,6 @@ layout: default title: intersection published: true -tags: [reference, data functions, functions, intersection, inline_json] --- [%CFEngine_function_prototype(list1, list2)%] diff --git a/reference/functions/ip2host.markdown b/reference/functions/ip2host.markdown index 9b81467de..a0c28246d 100644 --- a/reference/functions/ip2host.markdown +++ b/reference/functions/ip2host.markdown @@ -2,7 +2,6 @@ layout: default title: ip2host published: true -tags: [reference, communication functions, functions, ip2host, cached function] --- [%CFEngine_function_prototype(ip)%] diff --git a/reference/functions/iprange.markdown b/reference/functions/iprange.markdown index eedee4c1a..47b895fe9 100644 --- a/reference/functions/iprange.markdown +++ b/reference/functions/iprange.markdown @@ -2,7 +2,6 @@ layout: default title: iprange published: true -tags: [reference, communication functions, functions, iprange] --- [%CFEngine_function_prototype(range, optional_interface)%] diff --git a/reference/functions/irange.markdown b/reference/functions/irange.markdown index c0f8e4e35..83da72d83 100644 --- a/reference/functions/irange.markdown +++ b/reference/functions/irange.markdown @@ -2,7 +2,6 @@ layout: default title: irange published: true -tags: [reference, data functions, functions, irange] --- [%CFEngine_function_prototype(arg1, arg2)%] diff --git a/reference/functions/isdir.markdown b/reference/functions/isdir.markdown index 0df832945..788927809 100644 --- a/reference/functions/isdir.markdown +++ b/reference/functions/isdir.markdown @@ -2,7 +2,6 @@ layout: default title: isdir published: true -tags: [reference, files functions, functions, isdir] --- [%CFEngine_function_prototype(filename)%] diff --git a/reference/functions/isexecutable.markdown b/reference/functions/isexecutable.markdown index 6bb29464c..8a26b53e6 100644 --- a/reference/functions/isexecutable.markdown +++ b/reference/functions/isexecutable.markdown @@ -2,7 +2,6 @@ layout: default title: isexecutable published: true -tags: [reference, files functions, functions, isexecutable] --- [%CFEngine_function_prototype(filename)%] diff --git a/reference/functions/isgreaterthan.markdown b/reference/functions/isgreaterthan.markdown index b7866ccf5..eaac3845e 100644 --- a/reference/functions/isgreaterthan.markdown +++ b/reference/functions/isgreaterthan.markdown @@ -2,7 +2,6 @@ layout: default title: isgreaterthan published: true -tags: [reference, data functions, functions, isgreaterthan] --- [%CFEngine_function_prototype(value1, value2)%] diff --git a/reference/functions/isipinsubnet.markdown b/reference/functions/isipinsubnet.markdown index 18f3532d8..58995f456 100644 --- a/reference/functions/isipinsubnet.markdown +++ b/reference/functions/isipinsubnet.markdown @@ -2,7 +2,6 @@ layout: default title: isipinsubnet published: true -tags: [reference, communication functions, functions, subnet, networking, IPv4, IP, isipinsubnet] --- [%CFEngine_function_prototype(range, ip_address1, ip_address2, ...)%] diff --git a/reference/functions/islessthan.markdown b/reference/functions/islessthan.markdown index 76200dd96..c7e074c1f 100644 --- a/reference/functions/islessthan.markdown +++ b/reference/functions/islessthan.markdown @@ -2,7 +2,6 @@ layout: default title: islessthan published: true -tags: [reference, data functions, functions, islessthan] --- [%CFEngine_function_prototype(value1, value2)%] diff --git a/reference/functions/islink.markdown b/reference/functions/islink.markdown index 25899b725..7bdbdf8a7 100644 --- a/reference/functions/islink.markdown +++ b/reference/functions/islink.markdown @@ -2,7 +2,6 @@ layout: default title: islink published: true -tags: [reference, files functions, functions, islink] --- [%CFEngine_function_prototype(filename)%] diff --git a/reference/functions/isnewerthan.markdown b/reference/functions/isnewerthan.markdown index cdcf8779c..cc222fd8b 100644 --- a/reference/functions/isnewerthan.markdown +++ b/reference/functions/isnewerthan.markdown @@ -2,7 +2,6 @@ layout: default title: isnewerthan published: true -tags: [reference, files functions, functions, isnewerthan] --- [%CFEngine_function_prototype(newer, older)%] diff --git a/reference/functions/isplain.markdown b/reference/functions/isplain.markdown index 6770238e1..6bbca0c6a 100644 --- a/reference/functions/isplain.markdown +++ b/reference/functions/isplain.markdown @@ -2,7 +2,6 @@ layout: default title: isplain published: true -tags: [reference, files functions, functions, isplain] --- [%CFEngine_function_prototype(filename)%] diff --git a/reference/functions/isvariable.markdown b/reference/functions/isvariable.markdown index da205fc35..dc41bf435 100644 --- a/reference/functions/isvariable.markdown +++ b/reference/functions/isvariable.markdown @@ -2,7 +2,6 @@ layout: default title: isvariable published: true -tags: [reference, utility functions, functions, isvariable] --- [%CFEngine_function_prototype(var)%] diff --git a/reference/functions/join.markdown b/reference/functions/join.markdown index 6cc3fa271..a2e8db0bf 100644 --- a/reference/functions/join.markdown +++ b/reference/functions/join.markdown @@ -2,7 +2,6 @@ layout: default title: join published: true -tags: [reference, data functions, functions, join, inline_json] --- [%CFEngine_function_prototype(glue, list)%] diff --git a/reference/functions/lastnode.markdown b/reference/functions/lastnode.markdown index 1e1b97363..c3d2d7b25 100644 --- a/reference/functions/lastnode.markdown +++ b/reference/functions/lastnode.markdown @@ -2,7 +2,6 @@ layout: default title: lastnode published: true -tags: [reference, data functions, functions, lastnode] --- [%CFEngine_function_prototype(string, separator)%] diff --git a/reference/functions/laterthan.markdown b/reference/functions/laterthan.markdown index bdf85b7a1..6585f0d8e 100644 --- a/reference/functions/laterthan.markdown +++ b/reference/functions/laterthan.markdown @@ -2,7 +2,6 @@ layout: default title: laterthan published: true -tags: [reference, files functions, functions, laterthan] --- [%CFEngine_function_prototype(year, month, day, hour, minute, second)%] diff --git a/reference/functions/ldaparray.markdown b/reference/functions/ldaparray.markdown index 3162d1ace..f45786031 100644 --- a/reference/functions/ldaparray.markdown +++ b/reference/functions/ldaparray.markdown @@ -2,7 +2,6 @@ layout: default title: ldaparray published: true -tags: [reference, communication functions, functions, ldap] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/ldaplist.markdown b/reference/functions/ldaplist.markdown index 94fce99bb..7320e31e9 100644 --- a/reference/functions/ldaplist.markdown +++ b/reference/functions/ldaplist.markdown @@ -2,7 +2,6 @@ layout: default title: ldaplist published: true -tags: [reference, communication functions, functions, ldap, cached function] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/ldapvalue.markdown b/reference/functions/ldapvalue.markdown index 947461a47..23333390f 100644 --- a/reference/functions/ldapvalue.markdown +++ b/reference/functions/ldapvalue.markdown @@ -2,7 +2,6 @@ layout: default title: ldapvalue published: true -tags: [reference, communication functions, functions, ldap, cached function] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/length.markdown b/reference/functions/length.markdown index f68009e3c..ef11e368c 100644 --- a/reference/functions/length.markdown +++ b/reference/functions/length.markdown @@ -2,7 +2,6 @@ layout: default title: length published: true -tags: [reference, data functions, functions, length, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/lsdir.markdown b/reference/functions/lsdir.markdown index f3135e977..ae774177f 100644 --- a/reference/functions/lsdir.markdown +++ b/reference/functions/lsdir.markdown @@ -2,7 +2,6 @@ layout: default title: lsdir published: true -tags: [reference, files functions, functions, lsdir] --- [%CFEngine_function_prototype(path, regex, include_base)%] diff --git a/reference/functions/makerule.markdown b/reference/functions/makerule.markdown index 4d61d90eb..d97c0479a 100644 --- a/reference/functions/makerule.markdown +++ b/reference/functions/makerule.markdown @@ -2,7 +2,6 @@ layout: default title: makerule published: true -tags: [reference, files functions, functions, makerule, inline_json] --- [%CFEngine_function_prototype(target, sources)%] diff --git a/reference/functions/maparray.markdown b/reference/functions/maparray.markdown index bdda608e4..c16af3d15 100644 --- a/reference/functions/maparray.markdown +++ b/reference/functions/maparray.markdown @@ -2,7 +2,6 @@ layout: default title: maparray published: true -tags: [reference, data functions, functions, maparray, inline_json] --- [%CFEngine_function_prototype(pattern, array_or_container)%] diff --git a/reference/functions/mapdata.markdown b/reference/functions/mapdata.markdown index 2ebdaa39b..1558d3c2f 100644 --- a/reference/functions/mapdata.markdown +++ b/reference/functions/mapdata.markdown @@ -2,7 +2,6 @@ layout: default title: mapdata published: true -tags: [reference, data functions, functions, mapdata, inline_json] --- [%CFEngine_function_prototype(interpretation, pattern, array_or_container)%] diff --git a/reference/functions/maplist.markdown b/reference/functions/maplist.markdown index ec7f8160d..605c3964e 100644 --- a/reference/functions/maplist.markdown +++ b/reference/functions/maplist.markdown @@ -2,7 +2,6 @@ layout: default title: maplist published: true -tags: [reference, data functions, functions, maplist, inline_json] --- [%CFEngine_function_prototype(pattern, list)%] diff --git a/reference/functions/max.markdown b/reference/functions/max.markdown index 17f46d5b1..33fe3e1c7 100644 --- a/reference/functions/max.markdown +++ b/reference/functions/max.markdown @@ -2,7 +2,6 @@ layout: default title: max published: true -tags: [reference, data functions, functions, max, inline_json] --- [%CFEngine_function_prototype(list, sortmode)%] diff --git a/reference/functions/mean.markdown b/reference/functions/mean.markdown index 33afef535..4d13f72a7 100644 --- a/reference/functions/mean.markdown +++ b/reference/functions/mean.markdown @@ -2,7 +2,6 @@ layout: default title: mean published: true -tags: [reference, data functions, functions, mean, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/mergedata.markdown b/reference/functions/mergedata.markdown index 381517fc4..28686cc6a 100644 --- a/reference/functions/mergedata.markdown +++ b/reference/functions/mergedata.markdown @@ -2,7 +2,6 @@ layout: default title: mergedata published: true -tags: [reference, data functions, functions, json, merge, mergedata, container, wrap, extract, array, map, inline_json] --- [%CFEngine_function_prototype(one, two, etc)%] diff --git a/reference/functions/min.markdown b/reference/functions/min.markdown index b5106b568..37b6ec74a 100644 --- a/reference/functions/min.markdown +++ b/reference/functions/min.markdown @@ -2,7 +2,6 @@ layout: default title: min published: true -tags: [reference, data functions, functions, min, inline_json] --- [%CFEngine_function_prototype(list, sortmode)%] diff --git a/reference/functions/network_connections.markdown b/reference/functions/network_connections.markdown index 5bf7275af..a4f88d378 100644 --- a/reference/functions/network_connections.markdown +++ b/reference/functions/network_connections.markdown @@ -2,7 +2,6 @@ layout: default title: network_connections published: true -tags: [reference, network functions, functions, network_connections, network, connections, inet, inet6, tcp, tcp6, udp, udp6] --- [%CFEngine_function_prototype()%] diff --git a/reference/functions/none.markdown b/reference/functions/none.markdown index 01c185de5..b5a6adbe0 100644 --- a/reference/functions/none.markdown +++ b/reference/functions/none.markdown @@ -2,7 +2,6 @@ layout: default title: none published: true -tags: [reference, data functions, functions, none, inline_json] --- [%CFEngine_function_prototype(regex, list)%] diff --git a/reference/functions/not.markdown b/reference/functions/not.markdown index 857af3ca7..7745c5a7b 100644 --- a/reference/functions/not.markdown +++ b/reference/functions/not.markdown @@ -2,7 +2,6 @@ layout: default title: not published: true -tags: [reference, data functions, functions, not] --- [%CFEngine_function_prototype(expression)%] diff --git a/reference/functions/now.markdown b/reference/functions/now.markdown index e490fb7e9..e1a9be210 100644 --- a/reference/functions/now.markdown +++ b/reference/functions/now.markdown @@ -2,7 +2,6 @@ layout: default title: now published: true -tags: [reference, system functions, functions, now] --- [%CFEngine_function_prototype()%] diff --git a/reference/functions/nth.markdown b/reference/functions/nth.markdown index 24b420db6..90b9aedb8 100644 --- a/reference/functions/nth.markdown +++ b/reference/functions/nth.markdown @@ -2,7 +2,6 @@ layout: default title: nth published: true -tags: [reference, data functions, functions, nth, inline_json] --- [%CFEngine_function_prototype(list_or_container, position_or_key)%] diff --git a/reference/functions/on.markdown b/reference/functions/on.markdown index 1c7b40144..7d0ffb8ba 100644 --- a/reference/functions/on.markdown +++ b/reference/functions/on.markdown @@ -2,7 +2,6 @@ layout: default title: "on" published: true -tags: [reference, data functions, functions, "on"] --- [%CFEngine_function_prototype(year, month, day, hour, minute, second)%] diff --git a/reference/functions/or.markdown b/reference/functions/or.markdown index 22c42e467..94fe6751f 100644 --- a/reference/functions/or.markdown +++ b/reference/functions/or.markdown @@ -2,7 +2,6 @@ layout: default title: or published: true -tags: [reference, data functions, functions, or] --- [%CFEngine_function_prototype(...)%] diff --git a/reference/functions/packagesmatching.markdown b/reference/functions/packagesmatching.markdown index b2bcca5f8..816bd3529 100644 --- a/reference/functions/packagesmatching.markdown +++ b/reference/functions/packagesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: packagesmatching published: true -tags: [reference, utility functions, functions, packages, inventory, packagesmatching] --- [%CFEngine_function_prototype(package_regex, version_regex, arch_regex, method_regex)%] @@ -16,7 +15,7 @@ list of currently installed packages. The return is a data container with a list of package descriptions, looking like this: -``` +```json [ { "arch":"default", @@ -29,36 +28,30 @@ this: [%CFEngine_function_attributes(package_regex, version_regex, arch_regex, method_regex)%] -**Argument Descriptions:** - -* `package_regex` - Regular expression matching packge name -* `version_regex` - Regular expression matching package version -* `arch_regex` - Regular expression matching package architecutre -* `method_regex` - Regular expression matching package method (apt-get, rpm, etc ...) - -The following code extracts just the package names, then looks for -some desired packages, and finally reports if they are installed. - **IMPORTANT:** The data source used when querying depends on policy configuration. When `package_inventory` in `body common control` is configured, CFEngine will record the packages installed and the package updates available for the configured package modules. In the [Masterfiles Policy Framework][Masterfiles Policy Framework] `package_inventory` will be [configured](https://github.com/cfengine/masterfiles/blob/3dc1f629544b24261975ecf86e02554d4daf346e/promises.cf.in#L92) to the default for the hosts platform. Since only one `body common control` can be present in a policy set any bundles which use these functions will typically need to execute in the context of a full policy run. -If there is no `package_inventory` attribute such as on package module unsupported platforms or when a policy entry file other than promises.cf is selected with the `--file -f` argument then the legacy package methods data will be used. -At no time will both standard and legacy data be available to these functions. - -[%CFEngine_include_example(packagesmatching.cf)%] +However, the `packagesmatching` and `packageupdatesmatching` policy functions will look for and use the existing software inventory databases (available in `$(sys.statedir)`), even if the default package inventory is not configured. +This enables the usage of these policy functions in standalone policy files. But please note that you still need the default package inventory attribute specified in the policy framework for the software inventory databases to exist in the first place and for them to be maintained/updated. +If there is no `package_inventory` attribute (such as on package module unsupported platforms) and there are no software inventory databases available in `$(sys.statedir)` then the legacy package methods data will be used instead. +At no time will both the standard and the legacy data be available to these functions simultaneously. **Example:** -```cf3 -"all_packages" data => packagesmatching(".*", ".*", ".*", ".*"); -``` +The following code extracts just the package names, then looks for +some desired packages, and finally reports if they are installed. + + +[%CFEngine_include_example(packagesmatching.cf)%] **Refresh rules:** + * installed packages cache used by packagesmatching() is refreshed at the end of each agent run in accordance with constraints defined in the relevant package module body. * installed packages cache is refreshed after installing or removing a package. * installed packages cache is refreshed if no local cache exists. - This means a reliable way to force a refresh of CFEngine's internal package cache is to simply delete the local cache: + +This means a reliable way to force a refresh of CFEngine's internal package cache is to simply delete the local cache: ```cf3 $(sys.statedir)/packages_installed_.lmdb* @@ -71,6 +64,12 @@ $(sys.statedir)/software_packages.csv ``` -**History:** Introduced in CFEngine 3.6 +**History:** + +* Introduced in CFEngine 3.6 +* Function started using `package_module` based data sources by default, even if + there is no `package_inventory` attribute defined in `body common control` if + available in 3.23.0, 3.21.3 + **See also:** `packageupdatesmatching()`, [Package information cache tunables in the MPF][Masterfiles Policy Framework#Configure periodic package inventory refresh interval] diff --git a/reference/functions/packageupdatesmatching.markdown b/reference/functions/packageupdatesmatching.markdown index 086995ec6..4c96aabe1 100644 --- a/reference/functions/packageupdatesmatching.markdown +++ b/reference/functions/packageupdatesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: packageupdatesmatching published: true -tags: [reference, utility functions, functions, packages, inventory, packageupdatesmatching] --- [%CFEngine_function_prototype(package_regex, version_regex, arch_regex, method_regex)%] @@ -16,7 +15,7 @@ list of currently available packages. The return is a data container with a list of package descriptions, looking like this: -``` +```json [ { "arch":"default", @@ -29,32 +28,34 @@ this: [%CFEngine_function_attributes(package_regex, version_regex, arch_regex, method_regex)%] -**Argument Descriptions:** - -* `package_regex` - Regular expression matching packge name -* `version_regex` - Regular expression matching package version -* `arch_regex` - Regular expression matching package architecutre -* `method_regex` - Regular expression matching package method (apt-get, rpm, etc ...) - **IMPORTANT:** The data source used when querying depends on policy configuration. When `package_inventory` in `body common control` is configured, CFEngine will record the packages installed and the package updates available for the configured package modules. In the [Masterfiles Policy Framework][Masterfiles Policy Framework] `package_inventory` will be [configured](https://github.com/cfengine/masterfiles/blob/3dc1f629544b24261975ecf86e02554d4daf346e/promises.cf.in#L92) to the default for the hosts platform. Since only one `body common control` can be present in a policy set any bundles which use these functions will typically need to execute in the context of a full policy run. -If there is no `package_inventory` attribute such as on package module unsupported platforms or when a policy entry file other than promises.cf is selected with the `--file -f` argument then the legacy package methods data will be used. -At no time will both standard and legacy data be available to these functions. +However, the `packagesmatching` and `packageupdatesmatching` policy functions will look for and use the existing software inventory databases (available in `$(sys.statedir)`), even if the default package inventory is not configured. +This enables the usage of these policy functions in standalone policy files. But please note that you still need the default package inventory attribute specified in the policy framework for the software inventory databases to exist in the first place and for them to be maintained/updated. +If there is no `package_inventory` attribute (such as on package module unsupported platforms) and there are no software inventory databases available in `$(sys.statedir)` then the legacy package methods data will be used instead. +At no time will both the standard and the legacy data be available to these functions simultaneously. **Example:** ```cf3 -"all_package_updates" data => packageupdatesmatching(".*", ".*", ".*", ".*"); +vars: + "all_package_updates" + data => packageupdatesmatching(".*", # Package name regex + ".*", # Version regex + ".*", # Arch regex + ".*"); # Method regex ``` **Refresh rules:** + * updates cache used by packageupdatesmatching() is refreshed at the end of each agent run in accordance with constraints defined in the relevant package module body. * updates cache is refreshed every time `repo` type package is installed or removed * updates cache is refreshed if no local cache exists. - This means a reliable way to force a refresh of CFEngine's internal package cache is to simply delete the local cache: + +This means a reliable way to force a refresh of CFEngine's internal package cache is to simply delete the local cache: ```cf3 $(sys.statedir)/packages_updates_.lmdb* @@ -66,6 +67,12 @@ Or in the case of legacy package methods: $(sys.statedir)/software_patches_avail.csv ``` -**History:** Introduced in CFEngine 3.6 +**History:** + +* Introduced in CFEngine 3.6 +* Function started using `package_module` based data sources by default, even if + there is no `package_inventory` attribute defined in `body common control` if + available in 3.23.0, 3.21.3 + **See also:** `packagesmatching()`, [Package information cache tunables in the MPF][Masterfiles Policy Framework#Configure periodic package inventory refresh interval] diff --git a/reference/functions/parseintarray.markdown b/reference/functions/parseintarray.markdown index 8f458c9cc..4d9a16665 100644 --- a/reference/functions/parseintarray.markdown +++ b/reference/functions/parseintarray.markdown @@ -2,7 +2,6 @@ layout: default title: "parseintarray" published: true -tags: [reference, io functions, functions, parseintarray] --- **Prototype:** `parseintarray(array, input, comment, split, maxentries, maxbytes)`
      diff --git a/reference/functions/parsejson.markdown b/reference/functions/parsejson.markdown index 31234db07..3c2491da9 100644 --- a/reference/functions/parsejson.markdown +++ b/reference/functions/parsejson.markdown @@ -2,7 +2,6 @@ layout: default title: parsejson published: true -tags: [reference, io functions, functions, parsejson, json, container, inline_json] --- [%CFEngine_function_prototype(json_data)%] @@ -33,6 +32,10 @@ vars: data => '{ "key": "value" }'; ``` +**Notes:** + +* This functions does not parse _primitives_. + **History:** * Introduced in CFEngine 3.6.0 diff --git a/reference/functions/parserealarray.markdown b/reference/functions/parserealarray.markdown index 96306ea4e..28e19c547 100644 --- a/reference/functions/parserealarray.markdown +++ b/reference/functions/parserealarray.markdown @@ -2,7 +2,6 @@ layout: default title: "parserealarray" published: true -tags: [reference, io functions, functions, parserealarray] --- **Prototype:** `parserealarray(array, input, comment, split, maxentries, maxbytes)`
      diff --git a/reference/functions/parsestringarray.markdown b/reference/functions/parsestringarray.markdown index 4dbad1391..676557397 100644 --- a/reference/functions/parsestringarray.markdown +++ b/reference/functions/parsestringarray.markdown @@ -2,7 +2,6 @@ layout: default title: "parsestringarray" published: true -tags: [reference, io functions, functions, parseintarray, parserealarray, parsestringarray] --- **Prototype:** `parsestringarray(array, input, comment, split, maxentries, maxbytes)`
      diff --git a/reference/functions/parsestringarrayidx.markdown b/reference/functions/parsestringarrayidx.markdown index cce2e975c..a0397648f 100644 --- a/reference/functions/parsestringarrayidx.markdown +++ b/reference/functions/parsestringarrayidx.markdown @@ -2,7 +2,6 @@ layout: default title: parsestringarrayidx published: true -tags: [reference, io functions, functions, parsestringarrayidx] --- [%CFEngine_function_prototype(array, input, comment, split, maxentries, maxbytes)%] diff --git a/reference/functions/parseyaml.markdown b/reference/functions/parseyaml.markdown index 0e6b20fdc..e220898e8 100644 --- a/reference/functions/parseyaml.markdown +++ b/reference/functions/parseyaml.markdown @@ -2,7 +2,6 @@ layout: default title: parseyaml published: true -tags: [reference, io functions, functions, parseyaml, yaml, json, container] --- [%CFEngine_function_prototype(yaml_data)%] diff --git a/reference/functions/peerleader.markdown b/reference/functions/peerleader.markdown index 775b1f9a4..537fa6521 100644 --- a/reference/functions/peerleader.markdown +++ b/reference/functions/peerleader.markdown @@ -2,7 +2,6 @@ layout: default title: peerleader published: true -tags: [reference, communication functions, functions, peerleader] --- [%CFEngine_function_prototype(filename, regex, groupsize)%] diff --git a/reference/functions/peerleaders.markdown b/reference/functions/peerleaders.markdown index 2b5bcca1e..53d25ae23 100644 --- a/reference/functions/peerleaders.markdown +++ b/reference/functions/peerleaders.markdown @@ -2,7 +2,6 @@ layout: default title: peerleaders published: true -tags: [reference, communication functions, functions, peerleaders] --- [%CFEngine_function_prototype(filename, regex, groupsize)%] diff --git a/reference/functions/peers.markdown b/reference/functions/peers.markdown index acf804d6b..ad8e5228e 100644 --- a/reference/functions/peers.markdown +++ b/reference/functions/peers.markdown @@ -2,7 +2,6 @@ layout: default title: peers published: true -tags: [reference, communication functions, functions, peers] --- [%CFEngine_function_prototype(filename, regex, groupsize)%] diff --git a/reference/functions/processexists.markdown b/reference/functions/processexists.markdown index 828cb70fd..a2b9949e9 100644 --- a/reference/functions/processexists.markdown +++ b/reference/functions/processexists.markdown @@ -2,7 +2,6 @@ layout: default title: processexists published: true -tags: [reference, process functions, functions, processexists, process, processes, ps, cached function] --- [%CFEngine_function_prototype(regex)%] diff --git a/reference/functions/product.markdown b/reference/functions/product.markdown index c3785b01d..8d836e5cd 100644 --- a/reference/functions/product.markdown +++ b/reference/functions/product.markdown @@ -2,7 +2,6 @@ layout: default title: product published: true -tags: [reference, data functions, functions, product, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/randomint.markdown b/reference/functions/randomint.markdown index 622899005..b58ea2a5f 100644 --- a/reference/functions/randomint.markdown +++ b/reference/functions/randomint.markdown @@ -2,7 +2,6 @@ layout: default title: randomint published: true -tags: [reference, data functions, functions, randomint] --- [%CFEngine_function_prototype(lower, upper)%] diff --git a/reference/functions/read_module_protocol.markdown b/reference/functions/read_module_protocol.markdown index f5f52e3d1..a30e255ac 100644 --- a/reference/functions/read_module_protocol.markdown +++ b/reference/functions/read_module_protocol.markdown @@ -2,7 +2,6 @@ layout: default title: read_module_protocol published: true -tags: [reference, data functions, functions, "on"] --- [%CFEngine_function_prototype(file_path)%] diff --git a/reference/functions/readcsv.markdown b/reference/functions/readcsv.markdown index 5691fa1c3..698da166a 100644 --- a/reference/functions/readcsv.markdown +++ b/reference/functions/readcsv.markdown @@ -2,7 +2,6 @@ layout: default title: readcsv published: true -tags: [reference, io functions, functions, readcsv, CSV, container] --- [%CFEngine_function_prototype(filename, optional_maxbytes)%] diff --git a/reference/functions/readdata.markdown b/reference/functions/readdata.markdown index 38803832e..02c69c6ec 100644 --- a/reference/functions/readdata.markdown +++ b/reference/functions/readdata.markdown @@ -2,7 +2,6 @@ layout: default title: readdata published: true -tags: [reference, io functions, functions, readcsv, readjson, readyaml, readdata, readenvfile, CSV, JSON, YAML, ENV, container] --- [%CFEngine_function_prototype(filename, filetype)%] diff --git a/reference/functions/readenvfile.markdown b/reference/functions/readenvfile.markdown index 5943d0841..e3e85c45f 100644 --- a/reference/functions/readenvfile.markdown +++ b/reference/functions/readenvfile.markdown @@ -2,7 +2,6 @@ layout: default title: readenvfile published: true -tags: [reference, io functions, functions, readenvfile, json, env, os-release, container] --- [%CFEngine_function_prototype(filename, optional_maxbytes)%] diff --git a/reference/functions/readfile.markdown b/reference/functions/readfile.markdown index 9ccf09210..a7147e9b0 100644 --- a/reference/functions/readfile.markdown +++ b/reference/functions/readfile.markdown @@ -2,7 +2,6 @@ layout: default title: readfile published: true -tags: [reference, io functions, functions, readfile] --- [%CFEngine_function_prototype(filename, optional_maxbytes)%] diff --git a/reference/functions/readintarray.markdown b/reference/functions/readintarray.markdown index e936b40aa..01f4b3c24 100644 --- a/reference/functions/readintarray.markdown +++ b/reference/functions/readintarray.markdown @@ -2,7 +2,6 @@ layout: default title: "readintarray" published: true -tags: [reference, io functions, functions, readintarray] --- **Prototype:** `readintarray(array, filename, comment, split, maxentries, maxbytes)`
      diff --git a/reference/functions/readintlist.markdown b/reference/functions/readintlist.markdown index f4e312d5a..189502046 100644 --- a/reference/functions/readintlist.markdown +++ b/reference/functions/readintlist.markdown @@ -2,12 +2,9 @@ layout: default title: readintlist published: true -tags: [reference, io functions, functions, readintlist] --- -**Prototype:** `readintlist(filename, comment, split, maxentries, maxbytes)`
      - -**Return type:** `ilist` +[%CFEngine_function_prototype(filename, comment, split, maxentries, maxbytes)%] **Description:** Splits the file `filename` into separated values and returns the list. @@ -16,14 +13,7 @@ The `comment` field is a multiline regular expression and will strip out unwanted patterns from the file being read, leaving unstripped characters to be split into fields. Using the empty string (`""`) indicates no comments. -**Arguments**: - -* `filename` : File name to read, in the range `"?(/.*)` -* `comment` : [Unanchored][unanchored] regex matching comments, in the range `.*` -* `split` : [Unanchored][unanchored] regex to split data, in the range `.*` -* `maxentries` : Maximum number of entries to read, in the range -`0,99999999999` -* `maxbytes` : Maximum bytes to read, in the range `0,99999999999` +[%CFEngine_function_attributes(filename, comment, split, maxentries, maxbytes)%] **Example:** diff --git a/reference/functions/readjson.markdown b/reference/functions/readjson.markdown index 889fa2fcd..ced2b6859 100644 --- a/reference/functions/readjson.markdown +++ b/reference/functions/readjson.markdown @@ -2,7 +2,6 @@ layout: default title: readjson published: true -tags: [reference, io functions, functions, readjson, json, container] --- [%CFEngine_function_prototype(filename, optional_maxbytes)%] diff --git a/reference/functions/readrealarray.markdown b/reference/functions/readrealarray.markdown index 5b26d5822..6ee8d9e60 100644 --- a/reference/functions/readrealarray.markdown +++ b/reference/functions/readrealarray.markdown @@ -2,7 +2,6 @@ layout: default title: "readrealarray" published: true -tags: [reference, io functions, functions, readintarray, readrealarray, readstringarray] --- **Prototype:** `readrealarray(array, filename, comment, split, maxentries, maxbytes)`
      diff --git a/reference/functions/readreallist.markdown b/reference/functions/readreallist.markdown index 357c96bb1..82679807d 100644 --- a/reference/functions/readreallist.markdown +++ b/reference/functions/readreallist.markdown @@ -2,7 +2,6 @@ layout: default title: readreallist published: true -tags: [reference, io functions, functions, readreallist] --- **Prototype:** `readreallist(filename, comment, split, maxentries, maxbytes)`
      diff --git a/reference/functions/readstringarray.markdown b/reference/functions/readstringarray.markdown index e2937eeab..478ecdd4d 100644 --- a/reference/functions/readstringarray.markdown +++ b/reference/functions/readstringarray.markdown @@ -2,7 +2,6 @@ layout: default title: "readstringarray" published: true -tags: [reference, io functions, functions, readstringarray] --- **Prototype:** `readstringarray(array, filename, comment, split, maxentries, maxbytes)` diff --git a/reference/functions/readstringarrayidx.markdown b/reference/functions/readstringarrayidx.markdown index a37f62646..077faed4e 100644 --- a/reference/functions/readstringarrayidx.markdown +++ b/reference/functions/readstringarrayidx.markdown @@ -2,7 +2,6 @@ layout: default title: readstringarrayidx published: true -tags: [reference, io functions, functions, readstringarrayidx] --- [%CFEngine_function_prototype(array, filename, comment, split, maxentries, maxbytes)%] diff --git a/reference/functions/readstringlist.markdown b/reference/functions/readstringlist.markdown index 8a5276e84..2ed7ab872 100644 --- a/reference/functions/readstringlist.markdown +++ b/reference/functions/readstringlist.markdown @@ -2,7 +2,6 @@ layout: default title: readstringlist published: true -tags: [reference, io functions, functions, readstringlist] --- **Prototype:** `readstringlist(filename, comment, split, maxentries, maxbytes)` diff --git a/reference/functions/readtcp.markdown b/reference/functions/readtcp.markdown index 44322feb2..532da1835 100644 --- a/reference/functions/readtcp.markdown +++ b/reference/functions/readtcp.markdown @@ -2,7 +2,6 @@ layout: default title: readtcp published: true -tags: [reference, communication functions, functions, readtcp, cached function] --- [%CFEngine_function_prototype(hostnameip, port, sendstring, maxbytes)%] diff --git a/reference/functions/readyaml.markdown b/reference/functions/readyaml.markdown index 01dcd6c74..7b1091568 100644 --- a/reference/functions/readyaml.markdown +++ b/reference/functions/readyaml.markdown @@ -2,7 +2,6 @@ layout: default title: readyaml published: true -tags: [reference, io functions, functions, readyaml, yaml, json, container] --- [%CFEngine_function_prototype(filename, optional_maxbytes)%] diff --git a/reference/functions/regarray.markdown b/reference/functions/regarray.markdown index bc521da34..845c452df 100644 --- a/reference/functions/regarray.markdown +++ b/reference/functions/regarray.markdown @@ -2,7 +2,6 @@ layout: default title: regarray published: true -tags: [reference, data functions, functions, regarray] --- [%CFEngine_function_prototype(array, regex)%] diff --git a/reference/functions/regcmp.markdown b/reference/functions/regcmp.markdown index 713536b19..203493951 100644 --- a/reference/functions/regcmp.markdown +++ b/reference/functions/regcmp.markdown @@ -2,7 +2,6 @@ layout: default title: regcmp published: true -tags: [reference, data functions, functions, regcmp] --- [%CFEngine_function_prototype(regex, string)%] diff --git a/reference/functions/regex_replace.markdown b/reference/functions/regex_replace.markdown index 5c3652145..1579b2889 100644 --- a/reference/functions/regex_replace.markdown +++ b/reference/functions/regex_replace.markdown @@ -2,7 +2,6 @@ layout: default title: regex_replace published: true -tags: [reference, data functions, functions, regex_replace, pcre] --- [%CFEngine_function_prototype(string, regex, replacement, options)%] @@ -16,6 +15,7 @@ string in any order. Consult http://pcre.org/pcre.txt for the exact meaning of the uppercase options, and note that some can be turned on inside the regular expression, e.g. `(?s)`. +* `g`: global, replace all matches * `i`: case-insensitive * `m`: multiline (`PCRE_MULTILINE`) * `s`: dot matches newlines too (`PCRE_DOTALL`) diff --git a/reference/functions/regextract.markdown b/reference/functions/regextract.markdown index cef6c988c..681cd4da9 100644 --- a/reference/functions/regextract.markdown +++ b/reference/functions/regextract.markdown @@ -2,7 +2,6 @@ layout: default title: regextract published: true -tags: [reference, data functions, functions, regextract, pcre] --- [%CFEngine_function_prototype(regex, string, backref)%] diff --git a/reference/functions/registryvalue.markdown b/reference/functions/registryvalue.markdown index 2f857499f..28ce5fafa 100644 --- a/reference/functions/registryvalue.markdown +++ b/reference/functions/registryvalue.markdown @@ -2,7 +2,6 @@ layout: default title: registryvalue published: true -tags: [reference, system functions, functions, registryvalue] --- [%CFEngine_function_prototype(key, valueid)%] diff --git a/reference/functions/regldap.markdown b/reference/functions/regldap.markdown index a6fee9f67..ed180389d 100644 --- a/reference/functions/regldap.markdown +++ b/reference/functions/regldap.markdown @@ -2,7 +2,6 @@ layout: default title: regldap published: true -tags: [reference, communication functions, functions, ldap, cached function] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/regline.markdown b/reference/functions/regline.markdown index a0a26a1e1..9c868e0ed 100644 --- a/reference/functions/regline.markdown +++ b/reference/functions/regline.markdown @@ -2,7 +2,6 @@ layout: default title: regline published: true -tags: [reference, io functions, functions, regline] --- [%CFEngine_function_prototype(regex, filename)%] diff --git a/reference/functions/reglist.markdown b/reference/functions/reglist.markdown index 8529991d5..5f5af4058 100644 --- a/reference/functions/reglist.markdown +++ b/reference/functions/reglist.markdown @@ -2,7 +2,6 @@ layout: default title: reglist published: true -tags: [reference, data functions, functions, reglist, inline_json] --- [%CFEngine_function_prototype(list, regex)%] diff --git a/reference/functions/remoteclassesmatching.markdown b/reference/functions/remoteclassesmatching.markdown index 5cbc20fe2..9ee0f9499 100644 --- a/reference/functions/remoteclassesmatching.markdown +++ b/reference/functions/remoteclassesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: remoteclassesmatching published: true -tags: [reference, communication functions, functions, remoteclassesmatching] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/remotescalar.markdown b/reference/functions/remotescalar.markdown index c141e553f..3934ffb37 100644 --- a/reference/functions/remotescalar.markdown +++ b/reference/functions/remotescalar.markdown @@ -2,7 +2,6 @@ layout: default title: remotescalar published: true -tags: [reference, communication functions, functions, remotescalar, cached function] --- **This function is only available in CFEngine Enterprise.** diff --git a/reference/functions/returnszero.markdown b/reference/functions/returnszero.markdown index a4a1cbe0a..1d54aa77b 100644 --- a/reference/functions/returnszero.markdown +++ b/reference/functions/returnszero.markdown @@ -2,7 +2,6 @@ layout: default title: returnszero published: true -tags: [reference, utility functions, functions, returnszero, cached function] --- [%CFEngine_function_prototype(command, shell)%] diff --git a/reference/functions/reverse.markdown b/reference/functions/reverse.markdown index f8f2e42d7..91f75534a 100644 --- a/reference/functions/reverse.markdown +++ b/reference/functions/reverse.markdown @@ -2,7 +2,6 @@ layout: default title: reverse published: true -tags: [reference, data functions, functions, reverse, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/rrange.markdown b/reference/functions/rrange.markdown index f5c4a74f6..8502e618c 100644 --- a/reference/functions/rrange.markdown +++ b/reference/functions/rrange.markdown @@ -2,7 +2,6 @@ layout: default title: rrange published: true -tags: [reference, data functions, functions, rrange] --- [%CFEngine_function_prototype(arg1, arg2)%] diff --git a/reference/functions/selectservers.markdown b/reference/functions/selectservers.markdown index 1304b4ffa..64fb267bd 100644 --- a/reference/functions/selectservers.markdown +++ b/reference/functions/selectservers.markdown @@ -2,7 +2,6 @@ layout: default title: selectservers published: true -tags: [reference, communication functions, functions, selectservers] --- [%CFEngine_function_prototype(hostlist, port, query, regex, maxbytes, array)%] diff --git a/reference/functions/shuffle.markdown b/reference/functions/shuffle.markdown index 7838e4e44..48135af56 100644 --- a/reference/functions/shuffle.markdown +++ b/reference/functions/shuffle.markdown @@ -2,7 +2,6 @@ layout: default title: shuffle published: true -tags: [reference, data functions, functions, shuffle, inline_json] --- [%CFEngine_function_prototype(list, seed)%] diff --git a/reference/functions/some.markdown b/reference/functions/some.markdown index 8f9bdf1f9..2fab47afe 100644 --- a/reference/functions/some.markdown +++ b/reference/functions/some.markdown @@ -2,7 +2,6 @@ layout: default title: some published: true -tags: [reference, data functions, functions, some, inline_json] --- [%CFEngine_function_prototype(regex, list)%] diff --git a/reference/functions/sort.markdown b/reference/functions/sort.markdown index 8da44a9db..ede0cc2e5 100644 --- a/reference/functions/sort.markdown +++ b/reference/functions/sort.markdown @@ -2,7 +2,6 @@ layout: default title: sort published: true -tags: [reference, data functions, functions, sort, inline_json] --- [%CFEngine_function_prototype(list, mode)%] diff --git a/reference/functions/splayclass.markdown b/reference/functions/splayclass.markdown index 2633308b5..43857b252 100644 --- a/reference/functions/splayclass.markdown +++ b/reference/functions/splayclass.markdown @@ -2,7 +2,6 @@ layout: default title: splayclass published: true -tags: [reference, utility functions, functions, splayclass] --- [%CFEngine_function_prototype(input, policy)%] diff --git a/reference/functions/splitstring.markdown b/reference/functions/splitstring.markdown index 25578abdb..e22ed9af3 100644 --- a/reference/functions/splitstring.markdown +++ b/reference/functions/splitstring.markdown @@ -2,7 +2,6 @@ layout: default title: splitstring published: true -tags: [reference, data functions, functions, splitstring] --- [%CFEngine_function_prototype(string, regex, maxent)%] diff --git a/reference/functions/storejson.markdown b/reference/functions/storejson.markdown index 6be7f5e2e..eed076b43 100644 --- a/reference/functions/storejson.markdown +++ b/reference/functions/storejson.markdown @@ -2,7 +2,6 @@ layout: default title: storejson published: true -tags: [reference, io functions, functions, storejson, json, inline_json, container] --- [%CFEngine_function_prototype(data_container)%] diff --git a/reference/functions/strcmp.markdown b/reference/functions/strcmp.markdown index b889ced9b..84447c58e 100644 --- a/reference/functions/strcmp.markdown +++ b/reference/functions/strcmp.markdown @@ -2,7 +2,6 @@ layout: default title: strcmp published: true -tags: [reference, data functions, functions, strcmp] --- [%CFEngine_function_prototype(string1, string2)%] diff --git a/reference/functions/strftime.markdown b/reference/functions/strftime.markdown index 087145747..6e44cacca 100644 --- a/reference/functions/strftime.markdown +++ b/reference/functions/strftime.markdown @@ -2,7 +2,6 @@ layout: default title: strftime published: true -tags: [reference, data functions, functions, strftime] --- [%CFEngine_function_prototype(mode, template, time)%] diff --git a/reference/functions/string.markdown b/reference/functions/string.markdown index c745f56ae..a13b6f892 100644 --- a/reference/functions/string.markdown +++ b/reference/functions/string.markdown @@ -2,7 +2,6 @@ layout: default title: string published: true -tags: [reference, functions, string] --- [%CFEngine_function_prototype(arg)%] diff --git a/reference/functions/string_downcase.markdown b/reference/functions/string_downcase.markdown index 99d2cf93a..05b6bf77f 100644 --- a/reference/functions/string_downcase.markdown +++ b/reference/functions/string_downcase.markdown @@ -2,7 +2,6 @@ layout: default title: string_downcase published: true -tags: [reference, text functions, functions, text, case, downcase, string_downcase] --- [%CFEngine_function_prototype(data)%] diff --git a/reference/functions/string_head.markdown b/reference/functions/string_head.markdown index edb005e66..5c7dd86e4 100644 --- a/reference/functions/string_head.markdown +++ b/reference/functions/string_head.markdown @@ -2,7 +2,6 @@ layout: default title: string_head published: true -tags: [reference, text functions, functions, text, head, string_head, substring] --- [%CFEngine_function_prototype(data, max)%] diff --git a/reference/functions/string_length.markdown b/reference/functions/string_length.markdown index 6577a240b..e9f531168 100644 --- a/reference/functions/string_length.markdown +++ b/reference/functions/string_length.markdown @@ -2,7 +2,6 @@ layout: default title: string_length published: true -tags: [reference, text functions, functions, text, string_length, length, strlen, substring] --- [%CFEngine_function_prototype(data)%] diff --git a/reference/functions/string_mustache.markdown b/reference/functions/string_mustache.markdown index 3e3ba675f..d4e205b2f 100644 --- a/reference/functions/string_mustache.markdown +++ b/reference/functions/string_mustache.markdown @@ -2,7 +2,6 @@ layout: default title: string_mustache published: true -tags: [reference, text functions, functions, text, mustache, string_mustache, json] --- [%CFEngine_function_prototype(template_string, optional_data_container)%] diff --git a/reference/functions/string_replace.markdown b/reference/functions/string_replace.markdown index 9e7d044cb..32b66ff45 100644 --- a/reference/functions/string_replace.markdown +++ b/reference/functions/string_replace.markdown @@ -2,7 +2,6 @@ layout: default title: string_replace published: true -tags: [reference, data functions, functions, string_replace] --- [%CFEngine_function_prototype(string, match, replacement)%] diff --git a/reference/functions/string_reverse.markdown b/reference/functions/string_reverse.markdown index f5dfb3901..ea943fd0c 100644 --- a/reference/functions/string_reverse.markdown +++ b/reference/functions/string_reverse.markdown @@ -2,7 +2,6 @@ layout: default title: string_reverse published: true -tags: [reference, text functions, functions, text, reverse, string_reverse] --- [%CFEngine_function_prototype(data)%] diff --git a/reference/functions/string_split.markdown b/reference/functions/string_split.markdown index 7d5199dea..10994bfa2 100644 --- a/reference/functions/string_split.markdown +++ b/reference/functions/string_split.markdown @@ -2,7 +2,6 @@ layout: default title: string_split published: true -tags: [reference, data functions, functions, string_split] --- [%CFEngine_function_prototype(string, regex, maxent)%] diff --git a/reference/functions/string_tail.markdown b/reference/functions/string_tail.markdown index 2e3823454..b72e51a1e 100644 --- a/reference/functions/string_tail.markdown +++ b/reference/functions/string_tail.markdown @@ -2,7 +2,6 @@ layout: default title: string_tail published: true -tags: [reference, text functions, functions, text, string_tail, tail, substring] --- [%CFEngine_function_prototype(data, max)%] diff --git a/reference/functions/string_trim.markdown b/reference/functions/string_trim.markdown index 0c636002b..153fff677 100644 --- a/reference/functions/string_trim.markdown +++ b/reference/functions/string_trim.markdown @@ -2,7 +2,6 @@ layout: default title: string_trim published: true -tags: [reference, text functions, functions, text, string_trim, trim, substring] --- [%CFEngine_function_prototype(string)%] diff --git a/reference/functions/string_upcase.markdown b/reference/functions/string_upcase.markdown index 657b8c4ea..94d787dc4 100644 --- a/reference/functions/string_upcase.markdown +++ b/reference/functions/string_upcase.markdown @@ -2,7 +2,6 @@ layout: default title: string_upcase published: true -tags: [reference, text functions, functions, text, case, upcase, string_upcase] --- [%CFEngine_function_prototype(data)%] diff --git a/reference/functions/sublist.markdown b/reference/functions/sublist.markdown index e081c60e2..403298c98 100644 --- a/reference/functions/sublist.markdown +++ b/reference/functions/sublist.markdown @@ -2,7 +2,6 @@ layout: default title: sublist published: true -tags: [reference, data functions, functions, sublist, inline_json] --- [%CFEngine_function_prototype(list, head_or_tail, max_elements)%] diff --git a/reference/functions/sum.markdown b/reference/functions/sum.markdown index 70b906547..bf47a9475 100644 --- a/reference/functions/sum.markdown +++ b/reference/functions/sum.markdown @@ -2,7 +2,6 @@ layout: default title: sum published: true -tags: [reference, data functions, functions, sum, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/sysctlvalue.markdown b/reference/functions/sysctlvalue.markdown index d10b0244c..3300860a3 100644 --- a/reference/functions/sysctlvalue.markdown +++ b/reference/functions/sysctlvalue.markdown @@ -2,7 +2,6 @@ layout: default title: sysctlvalue published: true -tags: [reference, system functions, functions, sysctl, sysctlvalue] --- [%CFEngine_function_prototype(key)%] diff --git a/reference/functions/translatepath.markdown b/reference/functions/translatepath.markdown index f6caca167..94b46713b 100644 --- a/reference/functions/translatepath.markdown +++ b/reference/functions/translatepath.markdown @@ -2,7 +2,6 @@ layout: default title: translatepath published: true -tags: [reference, files functions, functions, translatepath] --- [%CFEngine_function_prototype(path)%] diff --git a/reference/functions/type.markdown b/reference/functions/type.markdown index 39dfe3ac0..abaa43c68 100644 --- a/reference/functions/type.markdown +++ b/reference/functions/type.markdown @@ -2,19 +2,13 @@ layout: default title: type published: true -tags: [reference, utility functions, functions, type] --- [%CFEngine_function_prototype(var, detail)%] -**Description:** Returns a variables type decription. +**Description:** Returns a variables type description. -**Return type:** `string` - -**Arguments:** - -* `var`: `string`, in the range `.*` -* `detail`: `boolean`, in the range: `true,false,yes,no,on,off` +[%CFEngine_function_attributes(var, detail)%] This function returns a variables type description as a string. The function expects a variable identifier as the first argument `var`. An optional second diff --git a/reference/functions/unique.markdown b/reference/functions/unique.markdown index ab0a1caba..f4131a162 100644 --- a/reference/functions/unique.markdown +++ b/reference/functions/unique.markdown @@ -2,7 +2,6 @@ layout: default title: unique published: true -tags: [reference, data functions, functions, unique, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/functions/url_get.markdown b/reference/functions/url_get.markdown index db8125556..2685c3345 100644 --- a/reference/functions/url_get.markdown +++ b/reference/functions/url_get.markdown @@ -2,7 +2,6 @@ layout: default title: url_get published: true -tags: [reference, communication functions, functions, url, www, file, ftp, http, https, url_get, inline_json] --- [%CFEngine_function_prototype(url, options_container)%] diff --git a/reference/functions/usemodule.markdown b/reference/functions/usemodule.markdown index d2f2f6ca7..87cbea763 100644 --- a/reference/functions/usemodule.markdown +++ b/reference/functions/usemodule.markdown @@ -2,7 +2,6 @@ layout: default title: usemodule published: true -tags: [reference, utility functions, functions, usemodule] --- [%CFEngine_function_prototype(module, args)%] diff --git a/reference/functions/userexists.markdown b/reference/functions/userexists.markdown index 7a68ef217..636185aa7 100644 --- a/reference/functions/userexists.markdown +++ b/reference/functions/userexists.markdown @@ -2,7 +2,6 @@ layout: default title: userexists published: true -tags: [reference, system functions, functions, userexists] --- [%CFEngine_function_prototype(user)%] diff --git a/reference/functions/validdata.markdown b/reference/functions/validdata.markdown index 6fd0066df..1a1c483c3 100644 --- a/reference/functions/validdata.markdown +++ b/reference/functions/validdata.markdown @@ -2,7 +2,6 @@ layout: default title: validdata published: true -tags: [reference, functions, validdata, JSON, context] --- [%CFEngine_function_prototype(data_container, type)%] diff --git a/reference/functions/validjson.markdown b/reference/functions/validjson.markdown index 759ca70b5..871a2e751 100644 --- a/reference/functions/validjson.markdown +++ b/reference/functions/validjson.markdown @@ -2,15 +2,14 @@ layout: default title: validjson published: true -tags: [reference, functions, validjson, JSON, context] --- -[%CFEngine_function_prototype(data_container)%] +[%CFEngine_function_prototype(string)%] -**Description:** Validates a JSON container from `data_container` and returns +**Description:** Validates a JSON container from `string` and returns `true` if the contents are valid JSON. -[%CFEngine_function_attributes(data_container)%] +[%CFEngine_function_attributes(string)%] **Example:** diff --git a/reference/functions/variablesmatching.markdown b/reference/functions/variablesmatching.markdown index e9e9401ef..fb689542f 100644 --- a/reference/functions/variablesmatching.markdown +++ b/reference/functions/variablesmatching.markdown @@ -2,7 +2,6 @@ layout: default title: variablesmatching published: true -tags: [reference, utility functions, functions, variablesmatching] --- [%CFEngine_function_prototype(name, tag1, tag2, ...)%] @@ -21,7 +20,7 @@ but not `inventory`, *both* are returned by variablesmatching(".*", "inventory", If you want logical AND semantics instead, you can make two calls to the function with one tag in each call and use the `intersection` function on the return values. -Variable tags are set using the [`meta`][Promise Types#meta] attribute. +Variable tags are set using the [`meta`][Promise types#meta] attribute. This function behaves exactly like `variablesmatching_as_data()` but returns just the list of all the variables. If you want their contents as well, see that diff --git a/reference/functions/variablesmatching_as_data.markdown b/reference/functions/variablesmatching_as_data.markdown index c16f6d99c..a079e1a36 100644 --- a/reference/functions/variablesmatching_as_data.markdown +++ b/reference/functions/variablesmatching_as_data.markdown @@ -2,7 +2,6 @@ layout: default title: variablesmatching_as_data published: true -tags: [reference, utility functions, functions, variablesmatching, variablesmatching_as_data] --- [%CFEngine_function_prototype(name, tag1, tag2, ...)%] @@ -22,7 +21,7 @@ but not `inventory`, *both* are returned by variablesmatching_as_data(".*", "inv If you want logical AND semantics instead, you can make two calls to the function with one tag in each call and use the `intersection` function on the return values. -Variable tags are set using the [`meta`][Promise Types#meta] attribute. +Variable tags are set using the [`meta`][Promise types#meta] attribute. This function behaves exactly like `variablesmatching()` but returns a data container with the full contents of all the variables instead of just their diff --git a/reference/functions/variance.markdown b/reference/functions/variance.markdown index 6206c0930..ab635cebe 100644 --- a/reference/functions/variance.markdown +++ b/reference/functions/variance.markdown @@ -2,7 +2,6 @@ layout: default title: variance published: true -tags: [reference, data functions, functions, variance, inline_json] --- [%CFEngine_function_prototype(list)%] diff --git a/reference/language-concepts.markdown b/reference/language-concepts.markdown index b21852cfd..5e814a78d 100644 --- a/reference/language-concepts.markdown +++ b/reference/language-concepts.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Language Concepts +title: Language concepts published: true sorting: 50 -tags: [overviews, language, syntax, concepts, promises] --- There is only one grammatical form for statements in the language: @@ -59,16 +58,16 @@ separate and re-usable parts. Effectively a body is like a promise attribute th CFEngine's boolean classifiers that describe context. -* [**Variables and Datatypes**][variables] +* [**Variables and datatypes**][variables] An association of the form "LVALUE *represents* RVALUE", where RVALUE may be a scalar value or a list of scalar values: a string, integer or real number. This documentation about the language concepts introduces in addition -* [**normal ordering**][Normal Ordering], +* [**normal ordering**][Normal ordering], * [**loops**][Loops], -* [**pattern matching and referencing**][Pattern Matching and Referencing], +* [**pattern matching and referencing**][Pattern matching and referencing], and * [**namespaces**][namespaces] @@ -110,7 +109,7 @@ The CFEngine 3 language has a few simple rules: In each of these cases, the right hand side is a user choice. - CFEngine uses many `constraint expressions' as part of the body of a promise. These take the form: left-hand-side (CFEngine word) '=>' right-hand-side (user defined data). This can take several forms: + CFEngine uses many _constraint expressions_ as part of the body of a promise. These take the form: left-hand-side (CFEngine word) '=>' right-hand-side (user defined data). This can take several forms: cfengine_word => user_defined_template(parameters) user_defined_template @@ -120,7 +119,7 @@ The CFEngine 3 language has a few simple rules: In each of these cases, the right hand side is a user choice. -## Filenames and Paths +## Filenames and paths Filenames in Unix-like operating systems use the forward slash '/' character for their directory separator. All references to file @@ -161,7 +160,7 @@ Paths beginning with a backslash are assumed to be win32 paths. They must begin with a drive letter or double-slash server name. Note that in many cases, you have `sys.inputdir` and other -[Special Variables] that work equally well on Windows and non-Windows +[Special variables] that work equally well on Windows and non-Windows system. Note in recent versions of Cygwin you can decide to use the diff --git a/reference/language-concepts/augments.markdown b/reference/language-concepts/augments.markdown index c5400cdce..1d8959230 100644 --- a/reference/language-concepts/augments.markdown +++ b/reference/language-concepts/augments.markdown @@ -3,7 +3,6 @@ layout: default title: Augments published: true sorting: 70 -tags: [manuals, language, syntax, concepts, augments] --- Augments files can be used to define variables and classes for use by @@ -53,11 +52,14 @@ In this example, `control_common_bundlesequence_end` is a special variable, hand To learn about more variables like this and ways to interact with the MPF without editing it, see the [MPF Reference documentation][Masterfiles Policy Framework]. The rest of this documentation page below focuses on the specifics of how augments files work, independently of everything they can be used for in the MPF. -## Augments Files ## +## Augments files ## There are two canonical augments files, `host_specific.json`, and `def.json` which may load additional Augments as specified by the [_augments_ key][Augments#augments]. +**Notes:** + +* CFEngine variables are **not** expanded unless otherwise noted. ### host_specific.json ### @@ -67,7 +69,6 @@ are automatically tagged with `source=cmdb`. Variables defined from this file ca **Notes:** * This file does not support the [_augments_ key][Augments#augments]. -* This file does not support expansion of CFEngine variables, including `sys` variables (unlike `def.json`). ### def.json ### @@ -80,10 +81,10 @@ The file `def.json` is found based on the location of the policy entry (the firs **Notes:** -* `sys` variables are expanded (unlike `host_specific.json`). +* `sys` variables are expanded in `def.json` and all subsequently loaded augments as specified by the `augments` key. * `def_preferred.json` will be used instead of `def.json` if it is present. This preferential loading can be disabled by providing the `--ignore-preferred-augments` option to the agent. -## Augments Keys ## +## Augments keys ## An augments file can contain the following keys: @@ -133,7 +134,7 @@ The above Augments results in `$(sys.policy_entry_dirname)/goodbye.cf` being add This key is supported in both `host_specific.json`, `def.json`, `def_preferred.json`, and augments loaded by the [_augments_ key][Augments#augments]. -Variables defined here can target a _namespace_ and or _bundle_ scope explicitly. When defined from `host_specific.json`, variables default to the `main` _bundle_ in the `data` _namespace_ (`$(data:main.MyVariable)`). +Variables defined here can target a _namespace_ and or _bundle_ scope explicitly. When defined from `host_specific.json`, variables default to the ```variables``` _bundle_ in the ```data``` _namespace_ (`$(data:variables.MyVariable)`). For example: @@ -238,6 +239,7 @@ bundle agent my_bundle ``` **Notes:** + * ```vars``` and ```variables``` keys are allowed concurrently in the same file. * If ```vars``` and ```variables``` keys in the same augments file define the same variable, the definition provided by the **```variables``` key wins**. @@ -302,6 +304,7 @@ Variables of other types than string can be defined too, like in this example ``` **Notes:** + * ```vars``` and ```variables``` keys are allowed concurrently in the same file. * If ```vars``` and ```variables``` keys in the same augments file define the same variable, the definition provided by the **```variables``` key wins**. @@ -314,12 +317,12 @@ Variables of other types than string can be defined too, like in this example This key is supported in both `host_specific.json`, `def.json`, `def_preferred.json`, and augments loaded by the augments key. Any class defined via augments will be evaluated and installed as -[**soft** classes][Classes and Decisions]. This key supports both +[**soft** classes][Classes and decisions]. This key supports both _array_ and _dict_ formats. For an array each element of the array is tested against currently defined classes as an [anchored regular expression][anchored] unless the string ends with ```::``` indicating it should be interpreted as a -[*class expression*][Classes and Decisions]. +[*class expression*][Classes and decisions]. **For example:** @@ -363,9 +366,9 @@ are supported when using the _dict_ structure. ``` Note that augments is processed at the very beginning of agent evaluation. You -can use any **hard** classes, [**persistent** classes][Classes and Decisions] +can use any **hard** classes, [**persistent** classes][Classes and decisions] , or classes defined earlier in the augments list. Test carefully, -custom [**soft** classes][Classes and Decisions] may not be defined early enough +custom [**soft** classes][Classes and decisions] may not be defined early enough for use. Thus: ```json @@ -396,6 +399,7 @@ for use. Thus: ``` results in + * `augments_class_from_rgex_my_always` being always defined. * `augments_class_from_regex_my_other_apache` will be defined if the classes diff --git a/reference/language-concepts/bodies.markdown b/reference/language-concepts/bodies.markdown index 79f2fb2d3..12f7f724b 100644 --- a/reference/language-concepts/bodies.markdown +++ b/reference/language-concepts/bodies.markdown @@ -3,7 +3,6 @@ layout: default title: Bodies published: true sorting: 20 -tags: [language, concepts, syntax, body] --- While the idea of a promise is very simple, the definition of a promise can @@ -172,21 +171,57 @@ Agents][Components] #### Default bodies -CFEngine 3.9 introduced a way to create default bodies. It allows defining, for given -promise and body types, a body that will be used each time no body is defined. -To use a body as default, name it `_` and put it -in the `bodydefault` namespace. For example, a default `action` body for `files` -promises will be named `files_action`, and in each `files` promise, if no -`action` attribute is set, the `files_action` action will be used. +Default bodies are automatically attached to promises not already using that +body in the default namespace. To use a body as default, name it +`_` and put it in the `bodydefault` namespace. + +```cf3 +body file control +{ + # Default bodies /must/ be defined in the /bodydefault/ namespace + namespace => "bodydefault"; +} + +body _ +{ + # Attributes set for body will be applied to all + # promises that do not already have a body of attached. +} +``` + +For example, a default `action` body for `files` promises will be named +`files_action`, and in each `files` promise, if no `action` attribute is set, +the `files_action` action will be used. **Note:** The default bodies **only** apply to promises in the `default` namespace. In the following example, we define a default `action` body for `files` -promises, that specifies an `action_policy => "warn"` to prevent actually modifying files -and to only warn about considered modifications. We define it once, -and don't have to explicitly put this body in all our `files` promises. +promises, that specifies an `action_policy => "warn"` to prevent actually +modifying files and to only warn about considered modifications. We define it +once, and don't have to explicitly put this body in all our `files` promises. +The example also illustrates how promises in a non-`default` namespace are +unaffected. ```cf3 +bundle agent example +{ + files: + + # Since the 'files_action' action body is defined in the 'bodydefault' namespce, + # and since this promise is in the 'default' namespace (no alternate namespace is + # declared previously) this promise will not actually modify the file content if + # it is not as promised. Instead it will warn that a change wants to be made. + + "/etc/motd" + content => "There are, in fact, rules. You have been notified."; + + # Since this promise has an action body attached, the default action body for + # files will not be applied and this file would be fixed. + + "/etc/issue.net" + content => "WARNING: You are being monitored. We are all being monitored. This is a cry for help.", + action => if_elapsed_day; +} body file control { namespace => "bodydefault"; @@ -199,6 +234,17 @@ body action files_action body file control { - namespace => "default"; + namespace => "not_affected"; +} + +bundle agent not_affected +{ + files: + "/etc/not-affected-by-bodydefault-files-action-body" + content => "Hello world!"; } ``` + +**History:** + +- Added in CFEngine 3.9.0 diff --git a/reference/language-concepts/bundles.markdown b/reference/language-concepts/bundles.markdown index 62d94dc7e..9b3ad12c1 100644 --- a/reference/language-concepts/bundles.markdown +++ b/reference/language-concepts/bundles.markdown @@ -3,7 +3,6 @@ layout: default title: Bundles published: true sorting: 10 -tags: [language, concepts, syntax, body, bundle] --- A bundle is a collection of promises. They allow to group related promises @@ -135,7 +134,7 @@ with the current bundle name. ### Scope All [variables][variables] in CFEngine are globally accessible. If you -refer to a variable by '$(unqualified)', then it is assumed to belong +refer to a variable by `$(unqualified)`, then it is assumed to belong to the current bundle. To access any other (scalar) variable, you must qualify the name, using the name of the bundle in which it is defined: diff --git a/reference/language-concepts/classes.markdown b/reference/language-concepts/classes.markdown index 18b1d1d97..cfdce53e8 100644 --- a/reference/language-concepts/classes.markdown +++ b/reference/language-concepts/classes.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Classes and Decisions +title: Classes and decisions published: true sorting: 50 -tags: [manuals, language, syntax, concepts, classes, decisions] --- Classes are used to apply promises only to particular environments, depending @@ -26,9 +25,9 @@ namespace scope. In [CFEngine Enterprise](https://cfengine.com/product-overview/), classes that are defined can be reported to the CFEngine Database Server and can be used there for reporting, grouping of hosts -and inventory management. For more information about how this is configured please read the documentation on [Enterprise Reporting][]. +and inventory management. For more information about how this is configured please read the documentation on [Enterprise reporting][]. -## Listing Classes +## Listing classes To see the first order of `hard classes` and `soft classes` run `cf-promises --show-classes` as a privileged user. Alternatively run `cf-agent @@ -68,7 +67,7 @@ Classes and variables have tags that describe their provenance (who created them) and purpose (why were they created). While you can provide your own tags for soft classes in policy with -the [`meta`][Promise Types#meta] attribute, there are some tags applied to hard classes and +the [`meta`][Promise types#meta] attribute, there are some tags applied to hard classes and other special cases. This list may change in future versions of CFEngine. @@ -93,7 +92,7 @@ Enterprise only: * `source=ldap`: this soft class or variable was created from an LDAP lookup. * `source=observation`: this class or variable came from a `measurements` system observation and will also have the `monitoring` tag. -## Hard Classes +## Hard classes Hard classes are discovered by CFEngine. Each time it wakes up, it discovers and reads properties of the environment or context in which it runs.It turns @@ -112,6 +111,12 @@ day, the week of the year, etc. Time-varying classes (tagged with `time_based`) will change if you do this a few times over the course of a week. +**Notes:** + +* Hard classes can **not** be undefined. If you try to undefine or cancel a hard + class an error will be emitted, for example `error: You cannot cancel a + reserved hard class 'cfengine' in post-condition classes`. + * CFEngine-specific classes * `any`: this class is always set * `am_policy_hub`, `policy_server`: set when the file @@ -173,19 +178,19 @@ of a week. * **See also:** `sys.fqhost`, `sys.uqhost`. - An arbitrary user-defined string (as specified in the `-D` command line option, or defined in a [`classes` promise][classes] promise or - [`classes` body][Promise Types#classes], + [`classes` body][Promise types#classes], `restart_class` in a `processes` promise, etc). -- The IP address octets of any active interface (in the form - `ipv4_192_0_0_1`, `ipv4_192_0_0`, - `ipv4_192_0`, `ipv4_192`), provided they - are not excluded by a regular expression in the file - `WORKDIR/inputs/ignore_interfaces.rx`. +- The IP address octets of any active interface (in the form `ipv4_192_0_0_1`, + `ipv4_192_0_0`, `ipv4_192_0`, `ipv4_192`), provided they are not excluded by + a regular expression in the file `WORKDIR/ignore_interfaces.rx` or `WORKDIR/inputs/ignore_interfaces.rx`. + - Note: Support and preference for `WORKDIR/ignore_interfaces.rx` was added + and is present in version `3.23.0` and later and in version `3.21.4` and later. - The names of the active interfaces (in the form `net_iface_xl0`, `net_iface_vr0`). - System status and entropy information reported by `cf-monitord`. -## Soft Classes +## Soft classes Soft classes are user-defined classes which you can use to implement your own classifications. @@ -278,7 +283,7 @@ reports: -### Negative Knowledge +### Negative knowledge If a class is set, then it is certain that the corresponding fact is true. However, that a class is not set could mean that something is not the case, or @@ -287,7 +292,7 @@ where the state of a class can change during the execution of a policy, depending on the [order][normal ordering] in which bundles and promises are evaluated. -## Making Decisions based on classes +## Making decisions based on classes Class guards are the most common way to restrict a promise to a specific context. Once stated the restriction applies until a new context is specified. A new promise type automatically resets to an unrestricted context (the unrestricted context is typically referred to as `any`). @@ -461,7 +466,7 @@ defined and that you must explicitly canonify when verifying classes. [%CFEngine_include_example(class-automatic-canonificiation.cf)%] -## Operators and Precedence +## Operators and precedence Classes promises define new classes based on combinations of old ones. This is how to make complex decisions in CFEngine, with readable results. It is like @@ -587,7 +592,7 @@ above and add [`and`][classes#and] or [`xor`][classes#xor] constraints to the single promise. Additionally classes can be defined or undefined as the result of a promise by -using a [classes body][Promise Types#classes]. To set a class if +using a [classes body][Promise types#classes]. To set a class if a promise is repaired, one might write: ```cf3 @@ -597,7 +602,7 @@ a promise is repaired, one might write: ``` These classes are `namespace` scoped by default. The -[`scope`][Promise Types#scope] attribute can be used to make them +[`scope`][Promise types#scope] attribute can be used to make them local to the bundle. It is recommended to use bundle scoped classes whenever possible. This example @@ -630,7 +635,7 @@ scoped. Finally, `restart_class` classes in `processes` are global. -### Class Scopes: A More Complex Example +### Class scopes: A more complex example ```cf3 body common control @@ -694,9 +699,9 @@ The standard library in the Masterfiles Policy Framework contains the [`feature`][lib/feature.cf] bundle which implements a useful model for defining classes for a period of time as well as canceling them on demand. -**See also:** [`persistance` classes attribute][classes#persistence], [`persist_time` in classes body][Promise Types#persist_time], [`lib/event.cf`][lib/event.cf] in the MPF, [`lib/feature.cf`][lib/feature.cf] in the MPF +**See also:** [`persistance` classes attribute][classes#persistence], [`persist_time` in classes body][Promise types#persist_time], [`lib/event.cf`][lib/event.cf] in the MPF, [`lib/feature.cf`][lib/feature.cf] in the MPF ## Canceling classes -You can cancel a class with a [`classes`][Promise Types#classes] body. +You can cancel a class with a [`classes`][Promise types#classes] body. See the `cancel_kept`, `cancel_notkept`, and `cancel_repaired` attributes. diff --git a/reference/language-concepts/loops.markdown b/reference/language-concepts/loops.markdown index a0d0c739a..00988847b 100644 --- a/reference/language-concepts/loops.markdown +++ b/reference/language-concepts/loops.markdown @@ -3,7 +3,6 @@ layout: default title: Loops published: true sorting: 70 -tags: [manuals, language, syntax, concepts, loops] --- There are no explicit loops in CFEngine, instead there are lists. To make a diff --git a/reference/language-concepts/modules.markdown b/reference/language-concepts/modules.markdown index ef8ad0013..85a2ede32 100644 --- a/reference/language-concepts/modules.markdown +++ b/reference/language-concepts/modules.markdown @@ -2,7 +2,6 @@ layout: default title: Modules published: true -tags: [language, concepts, syntax, modules] --- Modules allow users to extend the capabilities of CFEngine in a modular way, they can be easily added and upgraded independently of when you upgrade your CFEngine version. Several different types of modules are available. @@ -15,7 +14,7 @@ cfbs (CFEngine Build System) Modules provide a way to share and consume CFEngine ### Specification {% endcomment %} -## Promise Modules +## Promise modules Promise modules allow for the implementation of [*custom* promise types][promise-type-custom], extending the CFEngine Language. They communicate with `cf-agent` using the [*Promise Module Protocol*][promise-type-custom-protocol]. @@ -23,9 +22,9 @@ Promise modules allow for the implementation of [*custom* promise types][promise * Introduced 3.17.0 -## Package Modules +## Package modules -[Package Modules][Package Modules] implement the logic behind *packages* type promises, superseding the *package\_method* based implementation. They interact with package managers like `yum`, `apt`, `msiexec`, and `pip` to determine which packages are currently installed or have updates available as well as installing, upgrading or un-installing packages. +[Package modules][Package modules] implement the logic behind *packages* type promises, superseding the *package\_method* based implementation. They interact with package managers like `yum`, `apt`, `msiexec`, and `pip` to determine which packages are currently installed or have updates available as well as installing, upgrading or un-installing packages. Package modules communicate with `cf-agent` via the [Package Module Protocol][package-modules-the-api]. @@ -33,13 +32,13 @@ Package modules communicate with `cf-agent` via the [Package Module Protocol][pa * Introduced 3.7.0 -## Variables and Classes Modules +## Variables and classes modules -Variables and Classes Modules are the original way to extend CFEngine. The Variable and Class Module Protocol allows for *variables* and *classes* to be defined. The protocol can be interpreted by functions like [`usemodule()`][usemodule] and [`read_module_protocol()`][read_module_protocol] as well as output from [*commands* type promises][commands] with the [`module => "true"`][commands#module] attribute. +Variables and classes modules are the original way to extend CFEngine. The Variable and Class Module Protocol allows for *variables* and *classes* to be defined. The protocol can be interpreted by functions like [`usemodule()`][usemodule] and [`read_module_protocol()`][read_module_protocol] as well as output from [*commands* type promises][commands] with the [`module => "true"`][commands#module] attribute. -The choice of interpretation can depend on many factors but a primary differentiate between functions and classes relate to CFEngine's evaluation details. Functions are evaluated during early during policy execution unless they are explicitly guarded to delay execution. Commands promises are not executed until the bundle is actuated for it's three pass evaluation. +The choice of interpretation can depend on many factors but a primary differentiate between functions and classes relate to CFEngine's evaluation details. Functions are evaluated early during policy execution unless they are explicitly guarded to delay execution. Commands promises are not executed until the bundle is actuated for it's three pass evaluation. -Variables and Classes Modules are intended for use as system probes rather than additional configuration promises, especially now that promise modules are available. +Variables and classes modules are intended for use as system probes rather than additional configuration promises, especially now that promise modules are available. ### Specification diff --git a/reference/language-concepts/modules/package-module-api.markdown b/reference/language-concepts/modules/package-module-api.markdown index d920b0821..7d7955bd6 100644 --- a/reference/language-concepts/modules/package-module-api.markdown +++ b/reference/language-concepts/modules/package-module-api.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Package Modules +title: Package modules published: true sorting: 70 -tags: [reference, language concepts, modules, package module api] --- Package modules are back-ends that enable the package promise to work diff --git a/reference/language-concepts/namespaces.markdown b/reference/language-concepts/namespaces.markdown index 431c47e61..bfa099a3c 100644 --- a/reference/language-concepts/namespaces.markdown +++ b/reference/language-concepts/namespaces.markdown @@ -3,7 +3,6 @@ layout: default title: Namespaces published: true sorting: 100 -tags: [manuals, language, syntax, concepts, namespace] --- By default all promises are made in the `default` namespace. Specifying a namespace @@ -48,12 +47,12 @@ A common mistake is forgetting to specify `default:` when using bodies from the ## Variables -Variables (except for Special Variables) are assumed to be within the same scope +Variables (except for [Special variables][Special variables]) are assumed to be within the same scope as the promiser but can also be referenced fully qualified with the namespace. [%CFEngine_include_example(namespace_variable_references.cf)%] -[Special variables][Special Variables] are always accessible without a namespace +[Special variables][Special variables] are always accessible without a namespace prefix. For example, `this`, `mon`, `sys`, and `const` fall in this category. [%CFEngine_include_example(namespace_special_var_exception.cf)%] @@ -68,13 +67,13 @@ as the promiser but can also be referenced fully qualified with the namespace. Promises can only define classes within the current namespace. Classes are understood to refer to classes in the current namespace if a namespace is not -specified (except for Hard Classes). To refer to a +specified (except for Hard classes). To refer to a class in a different namespace prefix the class with the namespace suffixed by a colon (`:`). [%CFEngine_include_example(namespace_classes.cf)%] -[Hard classes][Classes and Decisions#Hard Classes] exist in all namespaces and +[Hard classes][Classes and decisions#Hard classes] exist in all namespaces and thus can be referred to from any namespace without qualification. [%CFEngine_include_example(namespace_hard_classes.cf)%] diff --git a/reference/language-concepts/normal-ordering.markdown b/reference/language-concepts/normal-ordering.markdown index d36e894e9..444d32f25 100644 --- a/reference/language-concepts/normal-ordering.markdown +++ b/reference/language-concepts/normal-ordering.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Normal Ordering +title: Normal ordering published: true sorting: 40 -tags: [manuals, language, syntax, concepts, ordering, depends_on] --- CFEngine takes a pragmatic point of view to ordering. When promising `scalar` @@ -78,6 +77,7 @@ evaluation perspective as bundles placed in files included in body common control inputs will be evaluated before bundles from file control inputs. The following steps are executed per-bundle for each file parsed, in this order: + 1. if it's a common bundle, evaluate **vars** promises 2. if it's a common bundle, evaluate **classes** promises 3. evaluate **vars** promises diff --git a/reference/language-concepts/pattern-matching-and-referencing.markdown b/reference/language-concepts/pattern-matching-and-referencing.markdown index 96de621e9..41b54703d 100644 --- a/reference/language-concepts/pattern-matching-and-referencing.markdown +++ b/reference/language-concepts/pattern-matching-and-referencing.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Pattern Matching and Referencing +title: Pattern matching and referencing published: true sorting: 80 -tags: [manuals, language, syntax, concepts, pattern, regexp, matching] --- One of the strengths of CFEngine 3 is the ability to recognize and exploit @@ -57,9 +56,9 @@ there were to exist a file `/home/mark/tmp/cf3_test`, then we would have: '$(match.0)' equal to `/home/mark/tmp/cf3_test' '$(match.1)' - equal to `3' + equal to `3` '$(match.2)' - equal to `test' + equal to `test` Note that because the pattern allows for an optional '2' or '3' to follow the letters `cf`, it is possible that `$(match.1)` would contain the empty string. @@ -71,7 +70,7 @@ would have '$(match.1)' equal to `' '$(match.2)' - equal to `widgets' + equal to `widgets` Now look at the edit bundle. This takes a parameter (which is the back-reference from the filename match), but it also uses back references to @@ -238,7 +237,7 @@ body replace_with comment(c) When applying regular expressions in paths, the path will first be split at the path separators, and each element matched independently. For example, this makes it possible to write expressions like `/home/.*/file` to match a single -file inside a lot of directories — the `.*` does not eat the whole string. +file inside a lot of directories - the `.*` does not eat the whole string. Note that whenever regular expressions are used in paths, the `/` is always used as the path separator, even on Windows. However, on Windows, if the diff --git a/reference/language-concepts/promises.markdown b/reference/language-concepts/promises.markdown index c5da03469..ff7799400 100644 --- a/reference/language-concepts/promises.markdown +++ b/reference/language-concepts/promises.markdown @@ -3,14 +3,13 @@ layout: default title: Promises published: true sorting: 30 -tags: [manuals, language, syntax, concepts, promises] --- One concept in CFEngine should stand out from the rest as being the most important: promises. Everything else is just an abstraction that allows us to declare promises and model the various actors in the system. -## Everything is a Promise +## Everything is a promise Everything in CFEngine 3 can be interpreted as a promise. Promises can be made about all kinds of different subjects, from file attributes, to the execution @@ -23,7 +22,7 @@ the proper owner to serve web pages via Apache. This simple but powerful idea allows a very practical uniformity in CFEngine syntax. -### Promise Types +### Promise types The `promise_type` defines what kind of object is making the promise. The type dictates how CFEngine interprets the promise body. These promise types are @@ -34,10 +33,10 @@ systems such as rpm and apt. Some promise types are common to all CFEngine components, while others can only be executed by one of them. `cf-serverd` cannot keep `packages` promises, and `cf-agent` cannot keep `access` promises. See the -[Promise Type reference][Promise Types] for a comprehensive +[Promise type reference][Promise types] for a comprehensive list of promise types. -### The Promiser +### The promiser The promiser is an object affected by a promise, and this can be anything: a file, a port on a network. It is the entity that is making a promise that a @@ -59,7 +58,7 @@ making][classes and decisions] section. Not all of these elements are necessary every time, but when you combine them they enable a wide range of behavior. -### Promise Example +### Promise example ```cf3 # Promise type @@ -88,7 +87,7 @@ CFEngine you can do this without having to execute the `touch`, `chmod`, and promise) that you want CFEngine to keep and you leave the details up to the tool. -### Promise Locking +### Promise locking When a promise is validated (has an outcome of kept or repaired) it is locked for [body agent control ifelapsed][cf-agent#ifelapsed] minutes (1 by default). Locks are based on a @@ -99,9 +98,9 @@ Promise locks can be useful for controlling frequency. `access`, `classes`, `defaults`, `meta`, `roles` and `vars` type promises do not participate in locking. -**See also:** [ifelapsed in body agent control][cf-agent#ifelapsed], [ifelapsed action body attribute][Promise Types#ifelapsed] +**See also:** [ifelapsed in body agent control][cf-agent#ifelapsed], [ifelapsed action body attribute][Promise types#ifelapsed] -### Promise Attributes +### Promise attributes Promise attributes have a type and a value. The type can be any of the [datatypes][datatypes] that are allowed for variables, and in addition @@ -151,7 +150,7 @@ bundle agent bad_example } ``` -### Implicit Promises +### Implicit promises Some promise types can have implicit behavior. For example, the following promise simply prints out a log message "hello world". @@ -170,4 +169,4 @@ commands: ``` These two promises have default attributes for everything except the -`promiser'. Both promises simply cause CFEngine to print a message. +_promiser_. Both promises simply cause CFEngine to print a message. diff --git a/reference/language-concepts/variables.markdown b/reference/language-concepts/variables.markdown index 5365c52d5..ac0e2597b 100644 --- a/reference/language-concepts/variables.markdown +++ b/reference/language-concepts/variables.markdown @@ -3,7 +3,6 @@ layout: default title: Variables published: true sorting: 60 -tags: [manuals, language, syntax, concepts, variables] --- Just like [classes][classes and decisions] are defined as @@ -18,7 +17,7 @@ data containers. * a list is a collection of scalars. * a data container is a lot like a JSON document, it can be a key-value map or an array or anything else allowed by the JSON standard with unlimited nesting. -## Scalar Variables +## Scalar variables Each scalar may have one of three types: string, int or real. String scalars are sequences of characters, integers are whole numbers, and reals are float @@ -65,7 +64,7 @@ values into int and real types, and if it cannot it will report an error. However, arguments to built-in [functions][Functions] check the defined argument type for consistency. -### Scalar Referencing and Expansion +### Scalar referencing and expansion Scalar variables are referenced by `$(my_scalar)` (or `${my_scalar}`) and expand to the single value they hold at that time. If you refer to a variable @@ -84,7 +83,7 @@ be escaped. [%CFEngine_include_example(quoting.cf)%] -### Scalar Size Limitations +### Scalar size limitations At the moment, up to 4095 bytes can fit into a scalar variable. This limitation may be removed in the future. @@ -118,7 +117,7 @@ vars: "my_rlist" rlist => { "567.89" }; ``` -### List Substitution and Expansion +### List substitution and expansion An entire list is referenced with the symbol '@' and can be passed in their entirety in any context where a list is expected as `@(list)`. For example, @@ -146,7 +145,7 @@ the list. In some function calls, `listname` instead of `@(listname)` is expected. See the specific function's documentation to be sure. -## Data Container Variables +## Data container variables The `data` containers can contain several levels of data structures, e.g. list of lists of key-value arrays. They are used to store @@ -164,7 +163,7 @@ variables. [%CFEngine_include_example(reference_values_inside_data.cf)%] -## Associative Arrays +## Associative arrays Associative arrays in CFEngine are fundamentally a collection of individual variables that together represent a data structure with key value pairs. They diff --git a/reference/macros.markdown b/reference/macros.markdown index a9f5f3d43..e9fd45136 100644 --- a/reference/macros.markdown +++ b/reference/macros.markdown @@ -4,7 +4,6 @@ title: Macros categories: [Reference, Macros] published: true alias: reference-macros.html -tags: [reference, syntax, if, ifdef, macros, minimum_version, feature] --- Macros allow you to target different versions of the CFEngine binaries / parser. @@ -192,7 +191,8 @@ syntax validation, so any CFEngine binary that is not compiled with the feature support macro will be able to exclude syntax from possibly incompatible versions. -Currently available features are : +Currently available features are: + * `xml` * `yaml` * `curl` diff --git a/reference/masterfiles-policy-framework.markdown b/reference/masterfiles-policy-framework.markdown index 5d0be8420..84871eb13 100644 --- a/reference/masterfiles-policy-framework.markdown +++ b/reference/masterfiles-policy-framework.markdown @@ -3,10 +3,9 @@ layout: default title: Masterfiles Policy Framework published: true sorting: 90 -tags: [reference, masterfiles, MPF] --- -The Masterfiles Policy Framework or MPF also commonly reffered to as simply +The Masterfiles Policy Framework or MPF also commonly referred to as simply masterfiles is the policy framework that ships with CFEngine. [%CFEngine_include_markdown(../../masterfiles/MPF.md)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-CFE_cfengine.markdown b/reference/masterfiles-policy-framework/cfe_internal-CFE_cfengine.markdown index 44f55044b..1e50ac1b9 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-CFE_cfengine.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-CFE_cfengine.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/CFE_cfengine.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/CFE_cfengine)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-core-watchdog-watchdog.markdown b/reference/masterfiles-policy-framework/cfe_internal-core-watchdog-watchdog.markdown index 1932dba05..00ed9cc21 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-core-watchdog-watchdog.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-core-watchdog-watchdog.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/core/watchdog/watchdog.cf published: true -tags: [reference, MPF, cfe_internal, core, watchdog] --- [%CFEngine_library_include(cfe_internal/core/watchdog/watchdog)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-core-watchdog.markdown b/reference/masterfiles-policy-framework/cfe_internal-core-watchdog.markdown index bb9d1c861..11a72ed0d 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-core-watchdog.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-core-watchdog.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/core/watchdog published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_include_markdown(../../masterfiles/cfe_internal/core/watchdog/README.md)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-core.markdown b/reference/masterfiles-policy-framework/cfe_internal-core.markdown index fea44cbc0..50527465b 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-core.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-core.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/core/ published: true -tags: [reference, cfe_internal, MPF] --- This directory contains internal management polcies related to CFEngine diff --git a/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation-federation.markdown b/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation-federation.markdown index e446a2b6f..1af18f3db 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation-federation.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation-federation.markdown @@ -2,9 +2,8 @@ layout: default title: cfe_internal/enterprise/federation/federation.cf published: true -tags: [reference, MPF, cfe_internal, federated reporting] --- -This policy file handles Federated Reporting setup and ongoing operations. +This policy file handles Federated reporting setup and ongoing operations. [%CFEngine_library_include(cfe_internal/enterprise/federation/federation)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation.markdown b/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation.markdown index 7ec6c5c17..1954e7017 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-enterprise-federation.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/enterprise/federation/ published: true -tags: [reference, MPF, cfe_internal, federated reporting] --- -This directory contains assets related to the function and configuration of [CFEngine Enterprise Federated Reporting][Federated Reporting]. +This directory contains assets related to the function and configuration of [CFEngine Enterprise Federated reporting][Federated reporting]. diff --git a/reference/masterfiles-policy-framework/cfe_internal-enterprise.markdown b/reference/masterfiles-policy-framework/cfe_internal-enterprise.markdown index 0a2a61fff..a90d170ce 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-enterprise.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-enterprise.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/enterprise/ published: true -tags: [reference, cfe_internal, MPF] --- This directory contains internal management polcies related to CFEngine diff --git a/reference/masterfiles-policy-framework/cfe_internal-recommendations.markdown b/reference/masterfiles-policy-framework/cfe_internal-recommendations.markdown index 3f923f859..4c224ea26 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-recommendations.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-recommendations.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/recommendations.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/recommendations)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_dc_workflow.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_dc_workflow.markdown index 1717f14d3..d50ac7021 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_dc_workflow.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_dc_workflow.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/cfe_internal_dc_workflow.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/cfe_internal_dc_workflow)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_update_from_repository.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_update_from_repository.markdown index aa1fe4c97..e59a3abcc 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_update_from_repository.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-cfe_internal_update_from_repository.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/cfe_internal_update_from_repository.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/cfe_internal_update_from_repository)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-lib.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-lib.markdown index 5f506140f..9e2f5c1f7 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-lib.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-lib.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/lib.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/lib)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-systemd_units.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-systemd_units.markdown index 7da2f17ff..e527c9a5d 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-systemd_units.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-systemd_units.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/systemd_units.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/systemd_units)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-update_bins.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-update_bins.markdown index c2076aaa3..c2de4a80b 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-update_bins.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-update_bins.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/update_bins.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/update_bins)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-update_policy.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-update_policy.markdown index 558e8ad7d..fe7d42f27 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-update_policy.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-update_policy.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/update_policy.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/update_policy)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update-update_processes.markdown b/reference/masterfiles-policy-framework/cfe_internal-update-update_processes.markdown index 1f88ae271..2c0412850 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update-update_processes.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update-update_processes.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/update_processes.cf published: true -tags: [reference, cfe_internal, MPF] --- [%CFEngine_library_include(cfe_internal/update/update_processes)%] diff --git a/reference/masterfiles-policy-framework/cfe_internal-update.markdown b/reference/masterfiles-policy-framework/cfe_internal-update.markdown index f32f83fa5..53d4d2bc8 100644 --- a/reference/masterfiles-policy-framework/cfe_internal-update.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal-update.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/update/ published: true -tags: [reference, cfe_internal, MPF] --- This directory contains internal management polcies related to the default diff --git a/reference/masterfiles-policy-framework/cfe_internal.markdown b/reference/masterfiles-policy-framework/cfe_internal.markdown index 4c3d498f4..5c29877d1 100644 --- a/reference/masterfiles-policy-framework/cfe_internal.markdown +++ b/reference/masterfiles-policy-framework/cfe_internal.markdown @@ -2,7 +2,6 @@ layout: default title: cfe_internal/ published: true -tags: [reference, cfe_internal, MPF] --- This directory contains policy related to the internal control and functioning diff --git a/reference/masterfiles-policy-framework/controls-cf-hub.markdown b/reference/masterfiles-policy-framework/controls-cf-hub.markdown index 86476f723..8a6dd39fa 100644 --- a/reference/masterfiles-policy-framework/controls-cf-hub.markdown +++ b/reference/masterfiles-policy-framework/controls-cf-hub.markdown @@ -2,7 +2,6 @@ layout: default title: controls/cf_hub.cf published: true -tags: [reference, controls, MPF] --- This is where `body hub control` is defined. `body hub control` is where diff --git a/reference/masterfiles-policy-framework/controls-cf_agent.markdown b/reference/masterfiles-policy-framework/controls-cf_agent.markdown index fbca2b3d4..3d3387117 100644 --- a/reference/masterfiles-policy-framework/controls-cf_agent.markdown +++ b/reference/masterfiles-policy-framework/controls-cf_agent.markdown @@ -2,7 +2,6 @@ layout: default title: controls/cf_agent.cf published: true -tags: [reference, controls, MPF] --- This is where `body agent control` is defined. `body agent control` is where diff --git a/reference/masterfiles-policy-framework/controls-cf_execd.markdown b/reference/masterfiles-policy-framework/controls-cf_execd.markdown index f6029ea41..65c42fed1 100644 --- a/reference/masterfiles-policy-framework/controls-cf_execd.markdown +++ b/reference/masterfiles-policy-framework/controls-cf_execd.markdown @@ -2,7 +2,6 @@ layout: default title: controls/cf_execd.cf published: true -tags: [reference, controls, MPF] --- This is where `body executor control` is defined. `body executor control` is where diff --git a/reference/masterfiles-policy-framework/controls-cf_monitord.markdown b/reference/masterfiles-policy-framework/controls-cf_monitord.markdown index 5c3ea5bf1..b80a80469 100644 --- a/reference/masterfiles-policy-framework/controls-cf_monitord.markdown +++ b/reference/masterfiles-policy-framework/controls-cf_monitord.markdown @@ -2,7 +2,6 @@ layout: default title: controls/cf_monitord.cf published: true -tags: [reference, controls, MPF] --- This is where `body monitor control` is defined. `body monitor control` is where diff --git a/reference/masterfiles-policy-framework/controls-cf_runagent.markdown b/reference/masterfiles-policy-framework/controls-cf_runagent.markdown index a312a75c1..ecda64ff1 100644 --- a/reference/masterfiles-policy-framework/controls-cf_runagent.markdown +++ b/reference/masterfiles-policy-framework/controls-cf_runagent.markdown @@ -2,7 +2,6 @@ layout: default title: controls/cf_runagent.cf published: true -tags: [reference, controls, MPF] --- This is where `body runagent control` is defined. `body runagent control` is where diff --git a/reference/masterfiles-policy-framework/controls-cf_serverd.markdown b/reference/masterfiles-policy-framework/controls-cf_serverd.markdown index 336498243..0f69edde8 100644 --- a/reference/masterfiles-policy-framework/controls-cf_serverd.markdown +++ b/reference/masterfiles-policy-framework/controls-cf_serverd.markdown @@ -2,7 +2,6 @@ layout: default title: controls/cf_serverd.cf published: true -tags: [reference, controls, MPF] --- This is where `body server control` is defined. `body server control` is where diff --git a/reference/masterfiles-policy-framework/controls-def.markdown b/reference/masterfiles-policy-framework/controls-def.markdown index 10448da40..104555bc7 100644 --- a/reference/masterfiles-policy-framework/controls-def.markdown +++ b/reference/masterfiles-policy-framework/controls-def.markdown @@ -2,7 +2,6 @@ layout: default title: controls/def.cf published: true -tags: [reference, controls, def.cf, MPF] --- This is where most common variables and classes are defined. Note its variable scope can be augmented with `def.json`. diff --git a/reference/masterfiles-policy-framework/controls-def_inputs.markdown b/reference/masterfiles-policy-framework/controls-def_inputs.markdown index c7dadd194..6e4346263 100644 --- a/reference/masterfiles-policy-framework/controls-def_inputs.markdown +++ b/reference/masterfiles-policy-framework/controls-def_inputs.markdown @@ -2,7 +2,6 @@ layout: default title: controls/def_inputs.cf published: true -tags: [reference, controls, MPF] --- This is where the list of policy files to include as defined from the augments diff --git a/reference/masterfiles-policy-framework/controls-reports.markdown b/reference/masterfiles-policy-framework/controls-reports.markdown index 5fe567cd9..bcfd17adc 100644 --- a/reference/masterfiles-policy-framework/controls-reports.markdown +++ b/reference/masterfiles-policy-framework/controls-reports.markdown @@ -2,7 +2,6 @@ layout: default title: controls/reports.cf published: true -tags: [reference, controls, MPF] --- This is where report settings for CFEngine Enterprise are found. Control which diff --git a/reference/masterfiles-policy-framework/controls-update_def.markdown b/reference/masterfiles-policy-framework/controls-update_def.markdown index 0b52fe6fe..8117e51ac 100644 --- a/reference/masterfiles-policy-framework/controls-update_def.markdown +++ b/reference/masterfiles-policy-framework/controls-update_def.markdown @@ -2,7 +2,6 @@ layout: default title: controls/update_def.cf published: true -tags: [reference, controls, MPF] --- This is where most common variables and classes are defined for the update diff --git a/reference/masterfiles-policy-framework/controls-update_def_inputs.markdown b/reference/masterfiles-policy-framework/controls-update_def_inputs.markdown index 76652f13f..71762a22f 100644 --- a/reference/masterfiles-policy-framework/controls-update_def_inputs.markdown +++ b/reference/masterfiles-policy-framework/controls-update_def_inputs.markdown @@ -2,7 +2,6 @@ layout: default title: controls/update_def_inputs.cf published: true -tags: [reference, controls, MPF] --- This is where the list of update related policy files to include as defined diff --git a/reference/masterfiles-policy-framework/controls.markdown b/reference/masterfiles-policy-framework/controls.markdown index 13610198f..c1989ec3f 100644 --- a/reference/masterfiles-policy-framework/controls.markdown +++ b/reference/masterfiles-policy-framework/controls.markdown @@ -2,7 +2,6 @@ layout: default title: controls/ published: true -tags: [reference, controls, MPF] --- This directory contains policy related to the internal control and functioning diff --git a/reference/masterfiles-policy-framework/inventory-any.markdown b/reference/masterfiles-policy-framework/inventory-any.markdown index b770d0eb9..8da56d649 100644 --- a/reference/masterfiles-policy-framework/inventory-any.markdown +++ b/reference/masterfiles-policy-framework/inventory-any.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/any.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related policy that can be run on any OS. This diff --git a/reference/masterfiles-policy-framework/inventory-debian.markdown b/reference/masterfiles-policy-framework/inventory-debian.markdown index 91c3879fe..222495429 100644 --- a/reference/masterfiles-policy-framework/inventory-debian.markdown +++ b/reference/masterfiles-policy-framework/inventory-debian.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/debian.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to debian hosts. diff --git a/reference/masterfiles-policy-framework/inventory-freebsd.markdown b/reference/masterfiles-policy-framework/inventory-freebsd.markdown index 2b965c893..3f25dcaeb 100644 --- a/reference/masterfiles-policy-framework/inventory-freebsd.markdown +++ b/reference/masterfiles-policy-framework/inventory-freebsd.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/freebsd.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to freebsd hosts. diff --git a/reference/masterfiles-policy-framework/inventory-generic.markdown b/reference/masterfiles-policy-framework/inventory-generic.markdown index 76aeb37fd..d2068558f 100644 --- a/reference/masterfiles-policy-framework/inventory-generic.markdown +++ b/reference/masterfiles-policy-framework/inventory-generic.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/generic.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to generic hosts. diff --git a/reference/masterfiles-policy-framework/inventory-linux.markdown b/reference/masterfiles-policy-framework/inventory-linux.markdown index f980f0b25..b5541cb01 100644 --- a/reference/masterfiles-policy-framework/inventory-linux.markdown +++ b/reference/masterfiles-policy-framework/inventory-linux.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/linux.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to linux hosts. diff --git a/reference/masterfiles-policy-framework/inventory-lsb.markdown b/reference/masterfiles-policy-framework/inventory-lsb.markdown index 2dc2d2d27..70cf71b93 100644 --- a/reference/masterfiles-policy-framework/inventory-lsb.markdown +++ b/reference/masterfiles-policy-framework/inventory-lsb.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/lsb.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to lsb hosts. diff --git a/reference/masterfiles-policy-framework/inventory-macos.markdown b/reference/masterfiles-policy-framework/inventory-macos.markdown index 4b658c062..20d9232a8 100644 --- a/reference/masterfiles-policy-framework/inventory-macos.markdown +++ b/reference/masterfiles-policy-framework/inventory-macos.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/macos.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to macos hosts. diff --git a/reference/masterfiles-policy-framework/inventory-os.markdown b/reference/masterfiles-policy-framework/inventory-os.markdown index 4541cfc05..f1cd41d92 100644 --- a/reference/masterfiles-policy-framework/inventory-os.markdown +++ b/reference/masterfiles-policy-framework/inventory-os.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/os.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to os hosts. diff --git a/reference/masterfiles-policy-framework/inventory-redhat.markdown b/reference/masterfiles-policy-framework/inventory-redhat.markdown index 210b1624a..58e2a466b 100644 --- a/reference/masterfiles-policy-framework/inventory-redhat.markdown +++ b/reference/masterfiles-policy-framework/inventory-redhat.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/redhat.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to redhat hosts. diff --git a/reference/masterfiles-policy-framework/inventory-suse.markdown b/reference/masterfiles-policy-framework/inventory-suse.markdown index 1c94b1669..a1211c438 100644 --- a/reference/masterfiles-policy-framework/inventory-suse.markdown +++ b/reference/masterfiles-policy-framework/inventory-suse.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/suse.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to suse hosts. diff --git a/reference/masterfiles-policy-framework/inventory-windows.markdown b/reference/masterfiles-policy-framework/inventory-windows.markdown index 583996b6b..05de8196b 100644 --- a/reference/masterfiles-policy-framework/inventory-windows.markdown +++ b/reference/masterfiles-policy-framework/inventory-windows.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/windows.cf published: true -tags: [reference, controls, MPF] --- This policy is inventory related to windows hosts. diff --git a/reference/masterfiles-policy-framework/inventory.markdown b/reference/masterfiles-policy-framework/inventory.markdown index 606665133..5ee048a9b 100644 --- a/reference/masterfiles-policy-framework/inventory.markdown +++ b/reference/masterfiles-policy-framework/inventory.markdown @@ -2,7 +2,6 @@ layout: default title: inventory/ published: true -tags: [reference, controls, MPF] --- [%CFEngine_include_markdown(../../masterfiles/inventory/README.md)%] diff --git a/reference/masterfiles-policy-framework/lib-autorun.markdown b/reference/masterfiles-policy-framework/lib-autorun.markdown index 3a0ffd270..7753fcf76 100644 --- a/reference/masterfiles-policy-framework/lib-autorun.markdown +++ b/reference/masterfiles-policy-framework/lib-autorun.markdown @@ -2,7 +2,6 @@ layout: default title: lib/autorun.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/autorun)%] diff --git a/reference/masterfiles-policy-framework/lib-bundles.markdown b/reference/masterfiles-policy-framework/lib-bundles.markdown index f9bc0a90b..8592320ef 100644 --- a/reference/masterfiles-policy-framework/lib-bundles.markdown +++ b/reference/masterfiles-policy-framework/lib-bundles.markdown @@ -2,7 +2,6 @@ layout: default title: lib/bundles.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/bundles)%] diff --git a/reference/masterfiles-policy-framework/lib-cfe_internal.markdown b/reference/masterfiles-policy-framework/lib-cfe_internal.markdown index 2c470b2e6..d2169eeb9 100644 --- a/reference/masterfiles-policy-framework/lib-cfe_internal.markdown +++ b/reference/masterfiles-policy-framework/lib-cfe_internal.markdown @@ -2,7 +2,6 @@ layout: default title: lib/cfe_internal.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/cfe_internal)%] diff --git a/reference/masterfiles-policy-framework/lib-cfe_internal_hub.markdown b/reference/masterfiles-policy-framework/lib-cfe_internal_hub.markdown index 8c56517b7..9cba4956d 100644 --- a/reference/masterfiles-policy-framework/lib-cfe_internal_hub.markdown +++ b/reference/masterfiles-policy-framework/lib-cfe_internal_hub.markdown @@ -2,7 +2,6 @@ layout: default title: lib/cfe_internal_hub.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/cfe_internal_hub)%] diff --git a/reference/masterfiles-policy-framework/lib-cfengine_enterprise_hub_ha.markdown b/reference/masterfiles-policy-framework/lib-cfengine_enterprise_hub_ha.markdown index 1848363b5..226b69d59 100644 --- a/reference/masterfiles-policy-framework/lib-cfengine_enterprise_hub_ha.markdown +++ b/reference/masterfiles-policy-framework/lib-cfengine_enterprise_hub_ha.markdown @@ -2,7 +2,6 @@ layout: default title: lib/cfengine_enterprise_hub_ha.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/cfengine_enterprise_hub_ha)%] diff --git a/reference/masterfiles-policy-framework/lib-commands.markdown b/reference/masterfiles-policy-framework/lib-commands.markdown index ad30033e2..c5521565c 100644 --- a/reference/masterfiles-policy-framework/lib-commands.markdown +++ b/reference/masterfiles-policy-framework/lib-commands.markdown @@ -2,7 +2,6 @@ layout: default title: lib/commands.cf published: true -tags: [reference, standard library, commands, MPF] --- See the [`commands` promises][commands] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-common.markdown b/reference/masterfiles-policy-framework/lib-common.markdown index e35b9c6e2..9c981d99f 100644 --- a/reference/masterfiles-policy-framework/lib-common.markdown +++ b/reference/masterfiles-policy-framework/lib-common.markdown @@ -2,11 +2,10 @@ layout: default title: lib/common.cf published: true -tags: [reference, standard library, common, MPF] --- See -the [common promise attributes][Promise Types#Common Promise Attributes] +the [common promise attributes][Promise types#Common promise attributes] documentation for a comprehensive reference on the body types and attributes used here. diff --git a/reference/masterfiles-policy-framework/lib-databases.markdown b/reference/masterfiles-policy-framework/lib-databases.markdown index 16a3543dc..c5d60907a 100644 --- a/reference/masterfiles-policy-framework/lib-databases.markdown +++ b/reference/masterfiles-policy-framework/lib-databases.markdown @@ -2,7 +2,6 @@ layout: default title: lib/databases.cf published: true -tags: [reference, standard library, databases, MPF] --- See the [`databases` promises][databases] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-edit_xml.markdown b/reference/masterfiles-policy-framework/lib-edit_xml.markdown index 662a6cc26..81e1cca6c 100644 --- a/reference/masterfiles-policy-framework/lib-edit_xml.markdown +++ b/reference/masterfiles-policy-framework/lib-edit_xml.markdown @@ -2,7 +2,6 @@ layout: default title: lib/edit_xml.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/edit_xml)%] diff --git a/reference/masterfiles-policy-framework/lib-event.markdown b/reference/masterfiles-policy-framework/lib-event.markdown index 38c2e8093..1e81ee78b 100644 --- a/reference/masterfiles-policy-framework/lib-event.markdown +++ b/reference/masterfiles-policy-framework/lib-event.markdown @@ -2,7 +2,6 @@ layout: default title: lib/event.cf published: true -tags: [reference, standard library, events, MPF] --- [%CFEngine_library_include(lib/event)%] diff --git a/reference/masterfiles-policy-framework/lib-examples.markdown b/reference/masterfiles-policy-framework/lib-examples.markdown index 9cda2c526..b060e5baf 100644 --- a/reference/masterfiles-policy-framework/lib-examples.markdown +++ b/reference/masterfiles-policy-framework/lib-examples.markdown @@ -2,7 +2,6 @@ layout: default title: lib/examples.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/examples)%] diff --git a/reference/masterfiles-policy-framework/lib-feature.markdown b/reference/masterfiles-policy-framework/lib-feature.markdown index 18f237565..d2f047c14 100644 --- a/reference/masterfiles-policy-framework/lib-feature.markdown +++ b/reference/masterfiles-policy-framework/lib-feature.markdown @@ -2,7 +2,6 @@ layout: default title: lib/feature.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/feature)%] diff --git a/reference/masterfiles-policy-framework/lib-files.markdown b/reference/masterfiles-policy-framework/lib-files.markdown index 6a5049adc..e0ae675e5 100644 --- a/reference/masterfiles-policy-framework/lib-files.markdown +++ b/reference/masterfiles-policy-framework/lib-files.markdown @@ -2,7 +2,6 @@ layout: default title: lib/files.cf published: true -tags: [reference, standard library, files, MPF] --- See the [`files` promises][files] and [`edit_line` bundles][edit_line] diff --git a/reference/masterfiles-policy-framework/lib-guest_environments.markdown b/reference/masterfiles-policy-framework/lib-guest_environments.markdown index f193f14e8..0f510cac4 100644 --- a/reference/masterfiles-policy-framework/lib-guest_environments.markdown +++ b/reference/masterfiles-policy-framework/lib-guest_environments.markdown @@ -2,7 +2,6 @@ layout: default title: lib/guest_environments.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/guest_environments)%] diff --git a/reference/masterfiles-policy-framework/lib-monitor.markdown b/reference/masterfiles-policy-framework/lib-monitor.markdown index 3d374caf0..b04055d72 100644 --- a/reference/masterfiles-policy-framework/lib-monitor.markdown +++ b/reference/masterfiles-policy-framework/lib-monitor.markdown @@ -2,7 +2,6 @@ layout: default title: lib/monitor.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/monitor)%] diff --git a/reference/masterfiles-policy-framework/lib-packages.markdown b/reference/masterfiles-policy-framework/lib-packages.markdown index 80c67407d..7a7f0fbda 100644 --- a/reference/masterfiles-policy-framework/lib-packages.markdown +++ b/reference/masterfiles-policy-framework/lib-packages.markdown @@ -2,7 +2,6 @@ layout: default title: lib/packages.cf published: true -tags: [reference, standard library, packages, MPF] --- See the [`packages` promises][packages] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-paths.markdown b/reference/masterfiles-policy-framework/lib-paths.markdown index 4c0365eba..697d24b35 100644 --- a/reference/masterfiles-policy-framework/lib-paths.markdown +++ b/reference/masterfiles-policy-framework/lib-paths.markdown @@ -2,7 +2,6 @@ layout: default title: lib/paths.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/paths)%] diff --git a/reference/masterfiles-policy-framework/lib-processes.markdown b/reference/masterfiles-policy-framework/lib-processes.markdown index e5bd1f2fb..cf237bc4e 100644 --- a/reference/masterfiles-policy-framework/lib-processes.markdown +++ b/reference/masterfiles-policy-framework/lib-processes.markdown @@ -2,7 +2,6 @@ layout: default title: lib/processes.cf published: true -tags: [reference, standard library, processes, MPF] --- See the [`processes` promises][processes] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-reports.markdown b/reference/masterfiles-policy-framework/lib-reports.markdown index 897ef732c..eb84d830d 100644 --- a/reference/masterfiles-policy-framework/lib-reports.markdown +++ b/reference/masterfiles-policy-framework/lib-reports.markdown @@ -2,7 +2,6 @@ layout: default title: lib/reports.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/reports)%] diff --git a/reference/masterfiles-policy-framework/lib-services.markdown b/reference/masterfiles-policy-framework/lib-services.markdown index 7741ce6de..b00f1f361 100644 --- a/reference/masterfiles-policy-framework/lib-services.markdown +++ b/reference/masterfiles-policy-framework/lib-services.markdown @@ -2,7 +2,6 @@ layout: default title: lib/services.cf published: true -tags: [reference, standard library, services, MPF] --- See the [`services` promises][services] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-stdlib.markdown b/reference/masterfiles-policy-framework/lib-stdlib.markdown index e1cf25827..4f83a5bec 100644 --- a/reference/masterfiles-policy-framework/lib-stdlib.markdown +++ b/reference/masterfiles-policy-framework/lib-stdlib.markdown @@ -2,7 +2,6 @@ layout: default title: lib/stdlib.cf published: true -tags: [reference, controls, MPF] --- [%CFEngine_library_include(lib/stdlib)%] diff --git a/reference/masterfiles-policy-framework/lib-storage.markdown b/reference/masterfiles-policy-framework/lib-storage.markdown index c5fd8cde9..3bf6bedb0 100644 --- a/reference/masterfiles-policy-framework/lib-storage.markdown +++ b/reference/masterfiles-policy-framework/lib-storage.markdown @@ -2,7 +2,6 @@ layout: default title: lib/storage.cf published: true -tags: [reference, standard library, storage, MPF] --- See the [`storage` promises][storage] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-testing.markdown b/reference/masterfiles-policy-framework/lib-testing.markdown index fffbc1ad0..68b7c5a5c 100644 --- a/reference/masterfiles-policy-framework/lib-testing.markdown +++ b/reference/masterfiles-policy-framework/lib-testing.markdown @@ -2,7 +2,6 @@ layout: default title: lib/testing.cf published: true -tags: [reference, standard library, testing, MPF] --- The `testing.cf` library provides bundles for working testing frameworks like diff --git a/reference/masterfiles-policy-framework/lib-users.markdown b/reference/masterfiles-policy-framework/lib-users.markdown index c34445b3e..a2dad9617 100644 --- a/reference/masterfiles-policy-framework/lib-users.markdown +++ b/reference/masterfiles-policy-framework/lib-users.markdown @@ -2,7 +2,6 @@ layout: default title: lib/users.cf published: true -tags: [reference, standard library, users, MPF] --- See the [`users` promises][users] documentation for a diff --git a/reference/masterfiles-policy-framework/lib-vcs.markdown b/reference/masterfiles-policy-framework/lib-vcs.markdown index cc52c349e..7bb9874da 100644 --- a/reference/masterfiles-policy-framework/lib-vcs.markdown +++ b/reference/masterfiles-policy-framework/lib-vcs.markdown @@ -2,7 +2,6 @@ layout: default title: lib/vcs.cf published: true -tags: [reference, standard library, vcs, MPF] --- The `vcs.cf` library provides bundles for working with version control tools. diff --git a/reference/masterfiles-policy-framework/lib.markdown b/reference/masterfiles-policy-framework/lib.markdown index 99cbe9ac9..86e8e78a0 100644 --- a/reference/masterfiles-policy-framework/lib.markdown +++ b/reference/masterfiles-policy-framework/lib.markdown @@ -2,10 +2,9 @@ layout: default title: lib/ published: true -tags: [reference, controls, MPF] --- -This directory contains the standard library akak COPBL or the Community Open +This directory contains the standard library aka COPBL or the Community Open Promise Body Library. The bodies and bundles found here are contributed and maintained by the CFEngine community. They codify many common and useful patterns. diff --git a/reference/masterfiles-policy-framework/modules-packages-vendored.markdown b/reference/masterfiles-policy-framework/modules-packages-vendored.markdown index c0302d938..ae39f8663 100644 --- a/reference/masterfiles-policy-framework/modules-packages-vendored.markdown +++ b/reference/masterfiles-policy-framework/modules-packages-vendored.markdown @@ -2,6 +2,5 @@ layout: default title: modules/packages/vendored/ published: true -tags: [reference, package modules, MPF] --- This directory tree is used for distributing package modules that are rendered into place with mustache. The modules found here are rendered into place if no plain copy is found in the parent directory. diff --git a/reference/masterfiles-policy-framework/modules-packages.markdown b/reference/masterfiles-policy-framework/modules-packages.markdown index 0b6f0dd8e..cef683896 100644 --- a/reference/masterfiles-policy-framework/modules-packages.markdown +++ b/reference/masterfiles-policy-framework/modules-packages.markdown @@ -2,7 +2,6 @@ layout: default title: modules/packages/ published: true -tags: [reference, package modules, MPF] --- This directory tree is used for distributing package modules. diff --git a/reference/masterfiles-policy-framework/modules-promises-cfengine.py.markdown b/reference/masterfiles-policy-framework/modules-promises-cfengine.py.markdown index 2a938a27e..2c1fe9774 100644 --- a/reference/masterfiles-policy-framework/modules-promises-cfengine.py.markdown +++ b/reference/masterfiles-policy-framework/modules-promises-cfengine.py.markdown @@ -2,7 +2,6 @@ layout: default title: modules/promises/cfengine.py published: true -tags: [reference, promise modules, MPF] --- {% raw %} ``` diff --git a/reference/masterfiles-policy-framework/modules-promises-cfengine.sh.markdown b/reference/masterfiles-policy-framework/modules-promises-cfengine.sh.markdown index e2c4229c8..bc94fa43c 100644 --- a/reference/masterfiles-policy-framework/modules-promises-cfengine.sh.markdown +++ b/reference/masterfiles-policy-framework/modules-promises-cfengine.sh.markdown @@ -2,7 +2,6 @@ layout: default title: modules/promises/cfengine.sh published: true -tags: [reference, promise modules, MPF] --- {% raw %} ``` diff --git a/reference/masterfiles-policy-framework/modules-promises.markdown b/reference/masterfiles-policy-framework/modules-promises.markdown index d02ac3a2f..66e7f2467 100644 --- a/reference/masterfiles-policy-framework/modules-promises.markdown +++ b/reference/masterfiles-policy-framework/modules-promises.markdown @@ -2,7 +2,6 @@ layout: default title: modules/promises/ published: true -tags: [reference, promise modules, MPF] --- This directory tree is used for distributing promise modules and supporting libraries. diff --git a/reference/masterfiles-policy-framework/modules.markdown b/reference/masterfiles-policy-framework/modules.markdown index c9cadeb9b..df704fb7e 100644 --- a/reference/masterfiles-policy-framework/modules.markdown +++ b/reference/masterfiles-policy-framework/modules.markdown @@ -2,7 +2,6 @@ layout: default title: modules/ published: true -tags: [reference, modules, MPF] --- This directory tree is used for distributing Modules. The [packages subtree][modules/packages/] is used for vendoring packages modules and the [promises sub-directory][modules/promises/] is used for promise modules, including the libraries used by promise modules. diff --git a/reference/masterfiles-policy-framework/no-distrib.markdown b/reference/masterfiles-policy-framework/no-distrib.markdown index 3c6eee43e..36665ab5a 100644 --- a/reference/masterfiles-policy-framework/no-distrib.markdown +++ b/reference/masterfiles-policy-framework/no-distrib.markdown @@ -3,7 +3,6 @@ layout: default title: .no-distrib/ published: true sorting: 20 -tags: [reference, .no-distrib , MPF] --- [%CFEngine_include_markdown(../../masterfiles/.no-distrib/README.md)%] diff --git a/reference/masterfiles-policy-framework/promises.markdown b/reference/masterfiles-policy-framework/promises.markdown index 9b28f0138..6b4a4c716 100644 --- a/reference/masterfiles-policy-framework/promises.markdown +++ b/reference/masterfiles-policy-framework/promises.markdown @@ -3,7 +3,6 @@ layout: default title: promises.cf published: true sorting: 10 -tags: [reference, promises.cf, MPF] --- `$(sys.inputdir)/promises.cf` is the default policy run by the agent. It is diff --git a/reference/masterfiles-policy-framework/services-autorun.markdown b/reference/masterfiles-policy-framework/services-autorun.markdown index 220000dfc..0492c5617 100644 --- a/reference/masterfiles-policy-framework/services-autorun.markdown +++ b/reference/masterfiles-policy-framework/services-autorun.markdown @@ -2,7 +2,6 @@ layout: default title: services/autorun/ published: true -tags: [reference, controls, MPF] --- [%CFEngine_include_markdown(../../masterfiles/services/autorun/README.md)%] diff --git a/reference/masterfiles-policy-framework/services-main.markdown b/reference/masterfiles-policy-framework/services-main.markdown index 03de966ac..6db4bdbbe 100644 --- a/reference/masterfiles-policy-framework/services-main.markdown +++ b/reference/masterfiles-policy-framework/services-main.markdown @@ -2,7 +2,6 @@ layout: default title: services/main.cf published: true -tags: [reference, controls, MPF] --- This directory is the suggested place to add your custom policies. diff --git a/reference/masterfiles-policy-framework/services.markdown b/reference/masterfiles-policy-framework/services.markdown index a7c6083fa..c52e5dc05 100644 --- a/reference/masterfiles-policy-framework/services.markdown +++ b/reference/masterfiles-policy-framework/services.markdown @@ -2,7 +2,6 @@ layout: default title: services/ published: true -tags: [reference, controls, MPF] --- This directory is the suggested place to add your custom policies. diff --git a/reference/masterfiles-policy-framework/standalone_self_upgrade.markdown b/reference/masterfiles-policy-framework/standalone_self_upgrade.markdown index 9d6fd7d55..ccb085a12 100644 --- a/reference/masterfiles-policy-framework/standalone_self_upgrade.markdown +++ b/reference/masterfiles-policy-framework/standalone_self_upgrade.markdown @@ -3,7 +3,6 @@ layout: default title: standalone_self_upgrade.cf published: true sorting: 30 -tags: [reference, policy entry, MPF] --- `$(sys.inputdir)/standalone_self_upgrade.cf` is an independent policy set entry diff --git a/reference/masterfiles-policy-framework/update.markdown b/reference/masterfiles-policy-framework/update.markdown index 25b985977..8a011331c 100644 --- a/reference/masterfiles-policy-framework/update.markdown +++ b/reference/masterfiles-policy-framework/update.markdown @@ -3,7 +3,6 @@ layout: default title: update.cf published: true sorting: 20 -tags: [reference, update.cf, MPF] --- `$(sys.inputdir)/update.cf` is responsible for updating diff --git a/reference/promise-types.markdown b/reference/promise-types.markdown index c1aad7dd7..fafd9feb5 100644 --- a/reference/promise-types.markdown +++ b/reference/promise-types.markdown @@ -1,16 +1,15 @@ --- layout: default -title: Promise Types +title: Promise types published: true sorting: 20 -tags: [reference, bundles, common, promises] --- Within a bundle, the promise types are executed in a round-robin fashion in the -following [normal ordering][Normal Ordering]. Which promise types are available +following [normal ordering][Normal ordering]. Which promise types are available depends on the [bundle][bundles] type: -| Promise Type | common | agent | server | monitor | +| Promise type | common | agent | server | monitor | |----------------|:------:|:-----:|:------:|:--------| | [defaults][defaults] - a default value for bundle parameters | x | x | x | x | | [classes][classes] - a class, representing a state of the system | x | x | x | x | @@ -34,7 +33,7 @@ depends on the [bundle][bundles] type: See each promise type's reference documentation for detailed lists of available attributes. -## Common Promise Attributes +## Common promise attributes The following attributes are available to all promise types. @@ -111,8 +110,13 @@ body agent control } ``` -**See also:** [promise locking][Promises#Promise Locking], [ifelapsed in body agent control][cf-agent#ifelapsed], -[`ifelapsed` and function caching][Functions#function caching] +**Notes:** + +* This is not a reliable way to control frequency over a long period of time. +* Locks provide simple but weak frequency control. +* Locks older than 4 weeks are automatically purged. + +**See also:** [promise locking][Promises#Promise Locking], [ifelapsed in body agent control][cf-agent#ifelapsed], [`ifelapsed` and function caching][Functions#function caching] **History:** @@ -639,6 +643,12 @@ body classes example In the above example, if the promise was already kept and nothing was done, cancel (undefine) any of the listed classes so that they are no longer defined. +**Notes:** + +* Hard classes can **not** be undefined. If you try to undefine or cancel a hard + class an error will be emitted, for example `error: You cannot cancel a + reserved hard class 'cfengine' in post-condition classes`. + **History:** This attribute was introduced in CFEngine version 3.0.4 (2010) #### cancel_repaired @@ -665,6 +675,12 @@ In the above example, if the promise was repaired and changes were made to the system, cancel (undefine) any of the listed classes so that they are no longer defined. +**Notes:** + +* Hard classes can **not** be undefined. If you try to undefine or cancel a hard + class an error will be emitted, for example `error: You cannot cancel a + reserved hard class 'cfengine' in post-condition classes`. + **History:** This attribute was introduced in CFEngine version 3.0.4 (2010) #### cancel_notkept @@ -692,6 +708,12 @@ In the above example, if the promise was not kept but nothing could be done, cancel (undefine) any of the listed classes so that they are no longer defined. +**Notes:** + +* Hard classes can **not** be undefined. If you try to undefine or cancel a hard + class an error will be emitted, for example `error: You cannot cancel a + reserved hard class 'cfengine' in post-condition classes`. + **History:** This attribute was introduced in CFEngine version 3.0.4 (2010) #### kept_returncodes @@ -885,7 +907,7 @@ body classes example } ``` -**See also:** [`persistance` classes attribute][classes#persistence], [`persist_time` in classes body][Promise Types#persist_time] +**See also:** [`persistance` classes attribute][classes#persistence], [`persist_time` in classes body][Promise types#persist_time] #### timer_policy @@ -1060,7 +1082,7 @@ automatically canonified when checking. You may need to use `canonify()` to convert strings containing invalid class characters into a valid class. In most cases, `if => something` and `if => not(something)` are opposite, -but because of [function skipping](Functions#Function_Skipping), both of these +but because of [function skipping][Functions#Function Skipping], both of these will be skipped if `something` is never resolved: ```cf3 @@ -1085,7 +1107,7 @@ skip. ### ifvarclass -**Description:** Deprecated, use [`if`][Promise Types#if] instead. +**Description:** Deprecated, use [`if`][Promise types#if] instead. **History:** New name `if` was introduced in 3.7.0, `ifvarclass` deprecated in 3.17.0. @@ -1236,7 +1258,7 @@ Output: **History:** Was introduced in 3.11.0 -## Common Body Attributes +## Common body attributes The following attributes are available to all body types. diff --git a/reference/promise-types/access.markdown b/reference/promise-types/access.markdown index 8d648c2d0..21b839221 100644 --- a/reference/promise-types/access.markdown +++ b/reference/promise-types/access.markdown @@ -2,18 +2,17 @@ layout: default title: access published: true -tags: [reference, bundle server, cf-serverd, access, server, promise types, acl, trust, encryption] --- Access promises are conditional promises made by resources living on the server. The promiser is the name of the resource affected and is interpreted to be a path, unless a -different `resource_type` is specified. Access is then granted to hosts listed in `admit_ips`, +different `resource_type` is specified. Access must then be granted to hosts listed in `admit_ips`, `admit_keys` and `admit_hostnames`, or denied using the counterparts `deny_ips`, `deny_keys` and `deny_hostnames`. -You layer the access policy by denying all access and then allowing it -only to selected clients, then denying to an even more restricted set. +By default access is denied. +As a policy writer you must specifically grant access. ```cf3 bundle server my_access_rules() @@ -118,6 +117,8 @@ promises will override less specific ones. ## Attributes ## +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + ### admit_hostnames **Description:** A list of hostnames or domains that should have access to the object. @@ -445,7 +446,7 @@ Here are the built-in `report_data_select` bodies `default_data_select_host()` a [%CFEngine_include_snippet(controls/reports.cf, .+default_data_select_policy_hub, \})%] -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] **History:** diff --git a/reference/promise-types/classes.markdown b/reference/promise-types/classes.markdown index 5eb650d9b..03a2308ed 100644 --- a/reference/promise-types/classes.markdown +++ b/reference/promise-types/classes.markdown @@ -2,7 +2,6 @@ layout: default title: classes published: true -tags: [bundle common, classes, promises] --- [Classes][classes] promises may be made in any bundle. Classes defined by @@ -76,6 +75,8 @@ bundle agent example ## Attributes ## +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + ### and **Description:** Combine class sources with AND @@ -308,7 +309,7 @@ classes: **History:** Was introduced in CFEngine 3.3.0 -**See also:** [`persistance` classes attribute][classes#persistence], [`persist_time` in classes body][Promise Types#persist_time] +**See also:** [`persistance` classes attribute][classes#persistence], [`persist_time` in classes body][Promise types#persist_time] ### not @@ -335,7 +336,7 @@ classes: Knowing that something is not the case is not the same as not knowing whether something is the case. That a class is not set could mean either. See the note -on [Negative Knowledge][classes and decisions]. +on [Negative knowledge][classes and decisions]. ### scope @@ -365,7 +366,7 @@ classes: scope => "bundle"; ``` -**See also:** [`scope` in `body classes`][Promise Types#scope] +**See also:** [`scope` in `body classes`][Promise types#scope] ### select_class diff --git a/reference/promise-types/commands.markdown b/reference/promise-types/commands.markdown index 80cf03489..eb343f22a 100644 --- a/reference/promise-types/commands.markdown +++ b/reference/promise-types/commands.markdown @@ -2,7 +2,6 @@ layout: default title: commands published: true -tags: [reference, bundle agent, commands, promises, promise types] --- Commands and [processes][processes] are separated cleanly. Restarting of @@ -44,7 +43,7 @@ commands: ``` When referring to executables the full path to the executable must be used. -When reffereing to executables whose paths contain spaces, you should quote +When referring to executables whose paths contain spaces, you should quote the entire program string separately so that CFEngine knows the name of the executable file. For example: @@ -126,12 +125,9 @@ So in the example above the command would be: **Description:** Allows to separate the arguments to the command from the command itself, using an slist. -As with `args`, it is convenient to separate command and arguments. -With `arglist` you can use a slist directly instead of having to -provide a single string as with `args`. That's particularly useful -when there are embedded spaces and quotes in your arguments, but also -when you want to get them directly from a slist without going through -`join()` or other functions. +As with `args`, it is convenient to separate command and arguments. With +`arglist` you can use a slist directly instead of having to provide a single +string as with `args`. The `arglist` is **appended** to `args` if that's defined, to preserve backwards compatibility. @@ -163,7 +159,7 @@ So in the example above the command would be: **Description:** Allows running the command in a 'sandbox'. -Command containment allows you to make a `sandbox' around a command, to run it +Command containment allows you to make a _sandbox_ around a command, to run it as a non-privileged user inside an isolated directory tree. **Type:** `body contain` @@ -183,7 +179,7 @@ exec_timeout => "60"; } ``` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### useshell @@ -324,7 +320,7 @@ exec_timeout => "30"; } ``` -**See also:** [`body action expireafter`][Promise Types#expireafter], [`body agent control expireafter`][cf-agent#expireafter], [`body executor control agent_expireafter`][cf-execd#agent_expireafter] +**See also:** [`body action expireafter`][Promise types#expireafter], [`body agent control expireafter`][cf-agent#expireafter], [`body executor control agent_expireafter`][cf-execd#agent_expireafter] #### chdir @@ -451,7 +447,7 @@ This attribute determines whether or not to expect the CFEngine module protocol. * `^meta=a,b,c` sets the class and variable tags for any following definitions to `a`, `b`, and `c` * `^persistence=10` sets any following classes to persist for 10 minutes (use 0 to reset) * `^persistence=0` sets any following classes to have no persistence (this is the default) -* lines which begin with a `+` are treated as classes to be defined (like -D). **NOTE:** classes are defined with the [`namespace` scope][Classes and Decisions]. +* lines which begin with a `+` are treated as classes to be defined (like -D). **NOTE:** classes are defined with the [`namespace` scope][Classes and decisions]. * lines which begin with a `-` are treated as classes to be undefined (like -N) * lines which begin with `=` are scalar variables to be defined * lines which begin with `=` and include `[]` are array variables to be defined diff --git a/reference/promise-types/custom.markdown b/reference/promise-types/custom.markdown index 73981f3ab..8d5fc8afa 100644 --- a/reference/promise-types/custom.markdown +++ b/reference/promise-types/custom.markdown @@ -2,7 +2,6 @@ layout: default title: custom published: true -tags: [bundle agent, promises] --- Custom promise types can be added as _Promise modules_. @@ -16,8 +15,8 @@ This documentation article provides a complete and detailed specification. It includes how to use them, how to implement them using modules, how the protocol works, etc. If you are interested in shorter tutorials, there are a few different ones available: -* [Introducing CFEngine Custom Promise Types - Installation and usage](https://cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/) -* [How to implement CFEngine Custom Promise Types in Python](https://cfengine.com/blog/2020/how-to-implement-cfengine-custom-promise-types-in-python/) +* [Introducing CFEngine Custom Promise types - Installation and usage](https://cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/) +* [How to implement CFEngine Custom Promise types in Python](https://cfengine.com/blog/2020/how-to-implement-cfengine-custom-promise-types-in-python/) * [How to implement CFEngine custom promise types in bash](https://cfengine.com/blog/2021/how-to-implement-cfengine-custom-promise-types-in-bash/) * [Custom Promise outcomes in Mission Portal](https://cfengine.com/blog/2021/custom-promise-outcomes-in-mission-portal/) @@ -72,7 +71,7 @@ These attributes are handled by the agent, and cannot be used inside promise mod * `comment` * `depends_on` * `handle` -* `meta` +* [`meta`][Promise types#meta] * `with` * `classes` @@ -99,7 +98,7 @@ Due to the implementation details, the following attributes from the `classes` b ### Evaluation passes and normal order In CFEngine, each bundle is evaluated in multiple passes (3 main passes for most promise types). -Within each evaluation pass of a bundle, the promises are not evaluated from top to bottom, but based on a [normal order][Normal Ordering] of the promise types. +Within each evaluation pass of a bundle, the promises are not evaluated from top to bottom, but based on a [normal order][Normal ordering] of the promise types. Custom promise types are added dynamically and don't have a predefined order, they are evaluated as they appear within a bundle (top to bottom), but at the end of each evaluation pass, after all the built in promise types. As with other promise types, we recommend not relying too much on this ordering, if you want some promises to be evaluated before others, use the `bundlesequence` or `depends_on` attribute to achieve this. @@ -123,7 +122,7 @@ from cfengine import PromiseModule, ValidationError class GitPromiseTypeModule(PromiseModule): - def validate_promise(self, promiser, attributes): + def validate_promise(self, promiser, attributes, metadata): if not promiser.startswith("/"): raise ValidationError(f"File path '{promiser}' must be absolute") for name, value in attributes.items(): @@ -132,7 +131,7 @@ class GitPromiseTypeModule(PromiseModule): if name == "repo" and type(value) is not str: raise ValidationError(f"'repo' must be string for git promise types") - def evaluate_promise(self, promiser, attributes): + def evaluate_promise(self, promiser, attributes, metadata): if not promiser.startswith("/"): raise ValidationError("File path must be absolute") @@ -403,12 +402,12 @@ This is done so the agent can print the messages while the promise is evaluating Log messages formatted like this must be before the JSON message, and it is optional. You can also include log messages in the JSON data: -``` +```json { "operation": "evaluate_promise", "promiser": "/opt/cfengine/masterfiles", "attributes": { - "repo": "https://github.com/cfengine/masterfiles"} + "repo": "https://github.com/cfengine/masterfiles" }, "log": [ { @@ -429,7 +428,7 @@ The JSON based protocol also supports the use of custom bodies. Custom bodies are sent as JSON objects within the respective attribute. The following is an example using the members attribute of the custom groups promise type: -``` +```cf3 body members foo_members { include => { "alice", "bob" }; @@ -439,16 +438,16 @@ body members foo_members bundle agent foo_group { groups: - "foo" - policy => "present", - members => foo_members; + "foo" + policy => "present", + members => foo_members; } ``` The attributes from the above example would be sent like this: -``` -"attributes": { +```json +{ "policy": "present", "members": { "include": ["alice", "bob"], @@ -474,7 +473,7 @@ The value may contain anything (including `=` signs) except for newlines and zer ##### Example requests in line based protocol -```conf +``` cf-agent 3.16.0 v1 operation=validate_promise @@ -495,7 +494,7 @@ log_level=info ##### Example response in line based protocol -```conf +``` git_promise_module 0.0.1 v1 line_based operation=validate_promise @@ -539,7 +538,7 @@ This enables the agent to filter the log messages based on log level, and also p See these tutorials / blog posts, for more examples or inspiration: -* [Introducing CFEngine Custom Promise Types - Installation and usage](https://cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/) -* [How to implement CFEngine Custom Promise Types in Python](https://cfengine.com/blog/2020/how-to-implement-cfengine-custom-promise-types-in-python/) -* [How to implement CFEngine Custom Promise Types in Bash](https://cfengine.com/blog/2021/how-to-implement-cfengine-custom-promise-types-in-bash/) +* [Introducing CFEngine Custom Promise types - Installation and usage](https://cfengine.com/blog/2020/introducing-cfengine-custom-promise-types/) +* [How to implement CFEngine Custom Promise types in Python](https://cfengine.com/blog/2020/how-to-implement-cfengine-custom-promise-types-in-python/) +* [How to implement CFEngine Custom Promise types in Bash](https://cfengine.com/blog/2021/how-to-implement-cfengine-custom-promise-types-in-bash/) * [Custom Promise outcomes in Mission Portal](https://cfengine.com/blog/2021/custom-promise-outcomes-in-mission-portal/) diff --git a/reference/promise-types/databases.markdown b/reference/promise-types/databases.markdown index 39767779d..0085d96e9 100644 --- a/reference/promise-types/databases.markdown +++ b/reference/promise-types/databases.markdown @@ -3,7 +3,6 @@ layout: default title: databases published: true sorting: 9999 -tags: [Reference, bundle agent, databases, promises, promise types] --- CFEngine can interact with commonly used database servers to keep @@ -157,7 +156,7 @@ a hierarchy of depth 1. **Type:** `body database_server` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### db_server_owner diff --git a/reference/promise-types/defaults.markdown b/reference/promise-types/defaults.markdown index f3945e12e..fac138f64 100644 --- a/reference/promise-types/defaults.markdown +++ b/reference/promise-types/defaults.markdown @@ -2,7 +2,6 @@ layout: default title: defaults published: true -tags: [reference, bundle common, defaults, promises] --- Defaults promises are related to [variables][variables]. If a variable or @@ -90,6 +89,8 @@ reports: ## Attributes ## +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + ### if_match_regex **Description:** If this [anchored][anchored] regular expression matches the diff --git a/reference/promise-types/files.markdown b/reference/promise-types/files.markdown index 62362aa74..632baa811 100644 --- a/reference/promise-types/files.markdown +++ b/reference/promise-types/files.markdown @@ -2,7 +2,6 @@ layout: default title: files published: true -tags: [reference, bundle agent, files, promises, files promises, promise types] --- Files promises manage all aspects of files. Presence, absence, file content, permissions, and ownership. File content can be fully or partially managed. @@ -164,12 +163,13 @@ When doing a recursive search, the files '.' and '..' are never included in the matched files, even if the regular expression in the `leaf_name` specifically allows them. -The filename `/dir/ect/ory/.` is a special case used with the `create` -attribute to indicate the directory named `/dir/ect/ory` and not any of -the files under it. If you really want to specify a regular expression -that matches any single-character filename, use `/dir/ect/ory/[\w\W]` as -your promise regular expression (you can't use `/dir/ect/ory/[^/]`, see -below for an explanation. +The filename `/dir/ect/ory/.` is a special case to avoid ambiguity between files +and directories, especially in the case of creation (both with and without the +explicit `create` attribute). Using /. ensures that a regular file is not +created when a directory is actually desired. If you really want to specify a +regular expression that matches any single-character filename, use +`/dir/ect/ory/[\w\W]` as your promise regular expression (you can't use +`/dir/ect/ory/[^/]`, see below for an explanation. Depth search refers to a search for file objects that starts from the one or more matched base-paths as shown in the example above. @@ -310,8 +310,8 @@ Depth search is not allowed with `edit_line` promises. Platforms that support named sockets (basically all Unix systems, but not Windows), may not work correctly when using a `files` promise to alter such a socket. This is a known issue, documented in -[CFE-1782](https://tracker.mender.io/browse/CFE-1782), and -[CFE-1830](https://tracker.mender.io/browse/CFE-1830). +[CFE-1782](https://northerntech.atlassian.net/browse/CFE-1782), and +[CFE-1830](https://northerntech.atlassian.net/browse/CFE-1830). *** @@ -323,7 +323,7 @@ alter such a socket. This is a known issue, documented in **Type:** `body acl` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] **History:** @@ -649,7 +649,7 @@ specify_default_aces => { "all:r" }; **Type:** `body changes` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### hash @@ -771,7 +771,7 @@ The copy_from body specifies the details for making remote copies. are re-used. Currently connection caching is done per pass in each bundle activation. -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### source @@ -931,7 +931,7 @@ body copy_from example } ``` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes], [`default_repository` in ```body agent control```][cf-agent#default_repository], [`edit_backup` in ```body edit_defaults```][files#edit_backup] +**See also:** [Common body attributes][Promise types#Common body attributes], [`default_repository` in ```body agent control```][cf-agent#default_repository], [`edit_backup` in ```body edit_defaults```][files#edit_backup] #### encrypt @@ -1460,7 +1460,7 @@ if the `create` attribute is explicitly used. **Type:** `body delete` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### dirlinks @@ -1539,7 +1539,7 @@ This should be used in combination with `file_select`. **Type:** `body depth_search` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### depth @@ -1684,7 +1684,7 @@ body depth_search example **Type:** `body edit_defaults` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### edit_backup @@ -2021,7 +2021,7 @@ bundle agent example **See also:** [template_method][files#template_method], `template_data`, `readjson()`, `parsejson()`, `readyaml()`, `parseyaml()`, `mergedata()`, -`data`, [Customize Message of the Day][Customize Message of the Day] +`data`, [Customize message of the day][Customize message of the day] ### edit_template_string @@ -2042,7 +2042,7 @@ bundle agent example **See also:** [template_method][files#template_method], `template_data`, `readjson()`, `parsejson()`, `readyaml()`, `parseyaml()`, `mergedata()`, -`data`, [Customize Message of the Day][Customize Message of the Day] +`data`, [Customize message of the day][Customize message of the day] ### edit_xml @@ -2052,7 +2052,7 @@ bundle agent example **Type:** `body file_select` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### leaf_name @@ -2474,7 +2474,7 @@ fifo **Type:** `body link_from` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### copy_patterns @@ -2754,7 +2754,7 @@ separator. **Type:** `body perms` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### bsdflags @@ -2889,7 +2889,7 @@ This is ignored on Windows, as the permission model uses ACLs. **Type:** `body rename` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### disable @@ -3113,7 +3113,7 @@ agent's current context. This allows conditional insertion. lines will not be rendered more than once unless they are included within a block. This includes blank lines. -Example contrived ```cfengine``` template: +Example contrived `cfengine` template: ```cf3 #This is a template file /templates/input.tmpl @@ -3136,7 +3136,7 @@ With text before and after. nameserver $(some.list) ``` -Example ```cfengine``` template for apache vhost directives: +Example `cfengine` template for apache vhost directives: ```cf3 [%CFEngine any:: %] diff --git a/reference/promise-types/files/edit_line.markdown b/reference/promise-types/files/edit_line.markdown index d4565900f..28a01010e 100644 --- a/reference/promise-types/files/edit_line.markdown +++ b/reference/promise-types/files/edit_line.markdown @@ -2,7 +2,6 @@ layout: default title: edit_line published: true -tags: [reference, bundle agent, edit_line, files promises, file editing] --- Line based editing is a simple model for editing files. Before XML, and @@ -88,7 +87,7 @@ There are several things to notice: - CFEngine makes a copy of the file you you want to edit. - CFEngine makes all the edits in the **copy** of the file. The filename is the same as your original file with the extension - .cf-after-edit appended. + `.cf-after-edit` appended. - After all promises are complete (the `vars`, `classes`, `delete_lines`, `field_edits`, `insert_lines`, `replace_patterns`, and finally `reports` promises), CFEngine checks to see if the new file is the same as the @@ -104,7 +103,7 @@ There are several things to notice: operating system), any application program will either see the old version of the file or the new one. There is no "window of opportunity" where a partially edited file can be seen (unless an - application intentionally looks for the .cf-after-edit file). + application intentionally looks for the `.cf-after-edit` file). Problems during editing (such as disk-full or permission errors) are likewise detected, and CFEngine will not rename a partial file over your original. @@ -190,7 +189,7 @@ Output: [%CFEngine_include_snippet(select_region.cf, #\+begin_src\s+example_output\s*, .*end_src)%] -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### Scope and lifetime diff --git a/reference/promise-types/files/edit_line/delete_lines.markdown b/reference/promise-types/files/edit_line/delete_lines.markdown index b11232d48..e35fc6a48 100644 --- a/reference/promise-types/files/edit_line/delete_lines.markdown +++ b/reference/promise-types/files/edit_line/delete_lines.markdown @@ -2,7 +2,6 @@ layout: default title: delete_lines published: true -tags: [reference, bundle agent, edit_line, files promises, file editing, delete_lines] --- This promise assures that certain lines exactly matching regular @@ -44,7 +43,7 @@ promise. **Type:** `body delete_select` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### delete_if_startwith_from_list diff --git a/reference/promise-types/files/edit_line/field_edits.markdown b/reference/promise-types/files/edit_line/field_edits.markdown index eed0f06c5..1e39ccb3b 100644 --- a/reference/promise-types/files/edit_line/field_edits.markdown +++ b/reference/promise-types/files/edit_line/field_edits.markdown @@ -2,7 +2,6 @@ layout: default title: field_edits published: true -tags: [reference, bundle agent, edit_line, files promises, file editing, field_edits] --- Certain types of text files are tabular in nature, with field separators (e.g. @@ -14,8 +13,8 @@ string: VARIABLE="one two three" ``` -View this line as a tabular line separated by " and with sub-separator -given by the space. +View this line as a tabular line separated by `"` and with sub-separator (`value_separator`) +being a space. Field editing allows us to edit tabular files in a unique way, adding and removing data from addressable fields. @@ -115,7 +114,7 @@ body edit_field col(split, col, newval, method) } ``` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### allow_blank_fields diff --git a/reference/promise-types/files/edit_line/insert_lines.markdown b/reference/promise-types/files/edit_line/insert_lines.markdown index 560e60c71..9fcc59fd6 100644 --- a/reference/promise-types/files/edit_line/insert_lines.markdown +++ b/reference/promise-types/files/edit_line/insert_lines.markdown @@ -2,7 +2,6 @@ layout: default title: insert_lines published: true -tags: [reference, bundle agent, edit_line, files promises, file editing, insert_lines] --- This promise type is part of the line-editing model. It inserts lines into @@ -204,7 +203,7 @@ Gimme three steps **Type:** `body insert_select` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### insert_if_startwith_from_list @@ -360,7 +359,7 @@ insert_if_not_contains_from_list => { "find_me_1", "find_me_2" }; **Type:** `body location` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes], [`location` bodies in the standard library](reference-masterfiles-policy-framework-lib-files.html#location-bodies), [`start` location body in the standard library](reference-masterfiles-policy-framework-lib-files.html#location-bodies), [`before(srt)` location body in the standard library](reference-masterfiles-policy-framework-lib-files.html#before), [`after(srt)` location body in the standard library](reference-masterfiles-policy-framework-lib-files.html#after) +**See also:** [Common body attributes][Promise types#Common body attributes], [`location` bodies in the standard library](reference-masterfiles-policy-framework-lib-files.html#location-bodies), [`start` location body in the standard library](reference-masterfiles-policy-framework-lib-files.html#location-bodies), [`before(srt)` location body in the standard library](reference-masterfiles-policy-framework-lib-files.html#before), [`after(srt)` location body in the standard library](reference-masterfiles-policy-framework-lib-files.html#after) #### before_after diff --git a/reference/promise-types/files/edit_line/replace_patterns.markdown b/reference/promise-types/files/edit_line/replace_patterns.markdown index 1bec40852..c2d4c2f38 100644 --- a/reference/promise-types/files/edit_line/replace_patterns.markdown +++ b/reference/promise-types/files/edit_line/replace_patterns.markdown @@ -2,7 +2,6 @@ layout: default title: replace_patterns published: true -tags: [reference, bundle agent, edit_line, files promises, file editing] --- This promise refers to arbitrary text patterns in a file. The pattern is @@ -49,7 +48,7 @@ pattern will match. **Type:** `body replace_with` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### occurrences diff --git a/reference/promise-types/files/edit_xml.markdown b/reference/promise-types/files/edit_xml.markdown index a41a5b988..4a726286b 100644 --- a/reference/promise-types/files/edit_xml.markdown +++ b/reference/promise-types/files/edit_xml.markdown @@ -2,7 +2,6 @@ layout: default title: edit_xml published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- The use of XML documents in systems configuration is widespread. XML @@ -22,7 +21,7 @@ new or manipulate existing XML documents. # build_xpath --> -## Common Attributes +## Common attributes diff --git a/reference/promise-types/files/edit_xml/build_xpath.markdown b/reference/promise-types/files/edit_xml/build_xpath.markdown index 05a87380b..b681b3988 100644 --- a/reference/promise-types/files/edit_xml/build_xpath.markdown +++ b/reference/promise-types/files/edit_xml/build_xpath.markdown @@ -2,7 +2,6 @@ layout: default title: build_xpath published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that a balanced XML tree, described by the given diff --git a/reference/promise-types/files/edit_xml/delete_attribute.markdown b/reference/promise-types/files/edit_xml/delete_attribute.markdown index 556886187..61ba3870d 100644 --- a/reference/promise-types/files/edit_xml/delete_attribute.markdown +++ b/reference/promise-types/files/edit_xml/delete_attribute.markdown @@ -2,7 +2,6 @@ layout: default title: delete_attribute published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that an attribute, with the given name, will not be diff --git a/reference/promise-types/files/edit_xml/delete_text.markdown b/reference/promise-types/files/edit_xml/delete_text.markdown index adab3448d..ea9412f02 100644 --- a/reference/promise-types/files/edit_xml/delete_text.markdown +++ b/reference/promise-types/files/edit_xml/delete_text.markdown @@ -2,7 +2,6 @@ layout: default title: delete_text published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that a value string, containing the matching diff --git a/reference/promise-types/files/edit_xml/delete_tree.markdown b/reference/promise-types/files/edit_xml/delete_tree.markdown index c8803c8b6..e953a42dd 100644 --- a/reference/promise-types/files/edit_xml/delete_tree.markdown +++ b/reference/promise-types/files/edit_xml/delete_tree.markdown @@ -2,7 +2,6 @@ layout: default title: delete_tree published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that a balanced XML tree, containing the matching diff --git a/reference/promise-types/files/edit_xml/insert_text.markdown b/reference/promise-types/files/edit_xml/insert_text.markdown index 49746a6dd..7d5694ceb 100644 --- a/reference/promise-types/files/edit_xml/insert_text.markdown +++ b/reference/promise-types/files/edit_xml/insert_text.markdown @@ -2,7 +2,6 @@ layout: default title: insert_text published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This proimse type assures that a value string, containing the matching diff --git a/reference/promise-types/files/edit_xml/insert_tree.markdown b/reference/promise-types/files/edit_xml/insert_tree.markdown index 2db775190..2c9d2f707 100644 --- a/reference/promise-types/files/edit_xml/insert_tree.markdown +++ b/reference/promise-types/files/edit_xml/insert_tree.markdown @@ -2,7 +2,6 @@ layout: default title: insert_tree published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that a diff --git a/reference/promise-types/files/edit_xml/set_attribute.markdown b/reference/promise-types/files/edit_xml/set_attribute.markdown index 8e061fa59..f0728db2d 100644 --- a/reference/promise-types/files/edit_xml/set_attribute.markdown +++ b/reference/promise-types/files/edit_xml/set_attribute.markdown @@ -2,7 +2,6 @@ layout: default title: set_attribute published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that an attribute, with the given name and value, will diff --git a/reference/promise-types/files/edit_xml/set_text.markdown b/reference/promise-types/files/edit_xml/set_text.markdown index d894b7345..97dd1b331 100644 --- a/reference/promise-types/files/edit_xml/set_text.markdown +++ b/reference/promise-types/files/edit_xml/set_text.markdown @@ -2,7 +2,6 @@ layout: default title: set_text published: true -tags: [reference, bundle agent, edit_xml, xml, files promises, file editing] --- This promise type assures that a matching value string will be present in the diff --git a/reference/promise-types/guest_environments.markdown b/reference/promise-types/guest_environments.markdown index d1428c57f..db1ac8e06 100644 --- a/reference/promise-types/guest_environments.markdown +++ b/reference/promise-types/guest_environments.markdown @@ -3,7 +3,6 @@ layout: default title: guest_environments published: true sorting: 9999 -tags: [reference, bundle agent, guest_environments, promises, promise types, virtual machines, agent, promises, libvirt, KVM, VMWare, deprecated] --- **WARNING**: Due to lack of use this promise type has been removed from the @@ -94,7 +93,7 @@ This attribute is required. **Type:** `body environment_interface` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### env_addresses @@ -182,7 +181,7 @@ host2:: **Type:** `body environment_resources` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### env_cpus diff --git a/reference/promise-types/measurements.markdown b/reference/promise-types/measurements.markdown index 04d1a8ca0..4df1f67f2 100644 --- a/reference/promise-types/measurements.markdown +++ b/reference/promise-types/measurements.markdown @@ -2,7 +2,6 @@ layout: default title: measurements published: true -tags: [reference, bundle monitor, measurements, monitoring, promise types] --- By default, CFEngine's monitoring component `cf-monitord` records performance @@ -105,7 +104,7 @@ cf-check dump /var/cfengine/state/cf_observations.lmdb By default in the [Masterfiles Policy Framework][Masterfiles Policy Framework], `cf-serverd` uses two variables, `def.default_data_select_host_monitoring_include` and `def.default_data_select_policy_hub_monitoring_include` to [configure which measurements will be included in enterprise reporting][mpf-configure-measurement-collection]. -On the hub side, reports are collected and measurements data is inserted into the [`MonitoringHG`][SQL Schema#Table: MonitoringYrMeta] [`MonitoringMgMeta`][SQL Schema#Table: MonitoringMgMeta] and [`MonitoringYrMeta`][SQL Schema#Table: MonitoringYrMeta] tables of the Enterprise Hub database. +On the hub side, reports are collected and measurements data is inserted into the [`MonitoringHG`][cfdb#Table: MonitoringYrMeta] [`MonitoringMgMeta`][cfdb#Table: MonitoringMgMeta] and [`MonitoringYrMeta`][cfdb#Table: MonitoringYrMeta] tables of the Enterprise Hub database. A diagnostic query to run with a [Custom Report in Mission Portal][Reporting UI]. @@ -123,7 +122,7 @@ data or not. SELECT * FROM monitoringmgmeta; ``` -Measurement data is presented in Mission Portal in the [`Measurements App`][Measurements App] and in the ```Measurements``` section of the [`Host Info page`][Hosts#Host Info]. +Measurement data is presented in Mission Portal in the [`Measurements App`][Measurements App] and in the ```Measurements``` section of the [`Host info page`][Hosts#Host info]. When policy is changed in regards to monitor bundles, both `cf-monitord` _and_ `cf-serverd` should be restarted in order to receive the updated policy. @@ -141,7 +140,7 @@ All measurements historical data is stored in `${sys.statedir}/cf_observations.l The `ts_key` file should not be altered. -Note that if a measurement has _always_ had a value of zero it will not be reported and so not available in Mission Portal Measurements or Host Info pages. +Note that if a measurement has _always_ had a value of zero it will not be reported and so not available in Mission Portal Measurements or Host info pages. It is important to specify a promise `handle` for measurement promises, as the names defined in the handle are used to determine the name of the log file or @@ -154,6 +153,8 @@ may be used in other promises in the form `$(mon.handle)`. ## Attributes ## +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + ### stream_type **Description:** The datatype being collected. @@ -292,7 +293,7 @@ This is an arbitrary string used in documentation only. **Type:** `body match_value` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### select_line_matching diff --git a/reference/promise-types/meta.markdown b/reference/promise-types/meta.markdown index af31ab613..48dabae08 100644 --- a/reference/promise-types/meta.markdown +++ b/reference/promise-types/meta.markdown @@ -2,7 +2,6 @@ layout: default title: meta published: true -tags: [reference, bundle common, meta, promises] --- Meta-data promises have no internal function. They are intended to be used to @@ -28,3 +27,90 @@ reports: ``` The value of meta data can be of the types `string` or `slist` or `data`. + +## Attributes + +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + +### data + +**Description:** A data container structure + +**Type:** `data` + +**Allowed input range:** (arbitrary string) + +**Example:** + +```cf3 +vars: + + "loaded1" data => readjson("/tmp/myfile.json", 40000); + "loaded2" data => parsejson('{"key":"value"}'); + "loaded3" data => readyaml("/tmp/myfile.yaml", 40000); + "loaded4" data => parseyaml('- key2: value2'); + "merged1" data => mergedata(loaded1, loaded2, loaded3, loaded4); + + # JSON or YAML can be inlined since CFEngine 3.7 + "inline1" data => '{"key":"value"}'; # JSON + "inline2" data => '---$(const.n)- key2: value2'; # YAML requires "---$(const.n)" header +``` + +### slist + +**Description:** A list of scalar strings + +**Type:** `slist` + +**Allowed input range:** (arbitrary string) + +**Example:** + +```cf3 +vars: + + "xxx" slist => { "literal1", "literal2" }; + "xxx1" slist => { "1", @(xxx) }; # interpolated in order + "yyy" slist => { + readstringlist( + "/home/mark/tmp/testlist", + "#[a-zA-Z0-9 ]*", + "[^a-zA-Z0-9]", + 15, + 4000 + ) + }; + + "zzz" slist => { readstringlist( + "/home/mark/tmp/testlist2", + "#[^\n]*", + ",", + 5, + 4000) + }; +``` + +**Notes:** + +Some [functions][Functions] return `slist`s, and an `slist` +may contain the values copied from another `slist`, `rlist`, or `ilist`. See +[`policy`](#policy). + + +### string + +**Description:** A scalar string + +**Type:** `string` + +**Allowed input range:** (arbitrary string) + +**Example:** + +```cf3 +vars: + + "xxx" string => "Some literal string..."; + "yyy" string => readfile( "/home/mark/tmp/testfile" , "33" ); +``` + diff --git a/reference/promise-types/methods.markdown b/reference/promise-types/methods.markdown index 9b5e76c43..7c8399074 100644 --- a/reference/promise-types/methods.markdown +++ b/reference/promise-types/methods.markdown @@ -2,7 +2,6 @@ layout: default title: methods published: true -tags: [reference, bundle agent, methods, promises, promise types] --- Methods are compound promises that refer to whole bundles of promises. @@ -136,16 +135,18 @@ example: `$(bundle.variable)`. ```cf3 bundle agent name { -methods: +classes: + "name_class"; +methods: "group name" usebundle => my_method, inherit => "true"; } - -body edit_defaults example +bundle agent my_method { -inherit => "true"; +reports: + "$(this.bundle) inherited class 'name_class'" if => "name_class"; } ``` @@ -164,7 +165,7 @@ Return values are limited to scalars. **Type:** `string` -**Allowed input range:** `[a-zA-Z0-9_$(){}\[\].:]+ +**Allowed input range:** `[a-zA-Z0-9_$(){}\[\].:]+` **Example:** diff --git a/reference/promise-types/packages-deprecated.markdown b/reference/promise-types/packages-deprecated.markdown index 9feb2b77c..848f6a98e 100644 --- a/reference/promise-types/packages-deprecated.markdown +++ b/reference/promise-types/packages-deprecated.markdown @@ -2,7 +2,6 @@ layout: default title: packages (deprecated) published: true -tags: [reference, bundle agent, packages, packages promises, promise types] --- **NOTE:** This package promise is deprecated and has been superseded by @@ -265,7 +264,7 @@ packages: **Type:** `body package_method` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### package_add_command @@ -593,7 +592,7 @@ package_list_update_ifelapsed => "240"; # 4 hours #### package_list_update_ifelapsed -**Description:** The [`ifelapsed`][Promise Types#ifelapsed] +**Description:** The [`ifelapsed`][Promise types#ifelapsed] locking time in between updates of the package list **Type:** `int` @@ -1109,7 +1108,7 @@ Update the package if an update is available (manager dependent). Equivalent to add if the package is not installed, and update if it is installed. Note: This attribute requires the specification of `package_version` and `package_select` in order to select the proper version to update to if -available. *See Also* [package_latest][lib/packages.cf#package_latest] +available. *See also* [package_latest][lib/packages.cf#package_latest] [package_specific_latest][lib/packages.cf#package_specific_latest] in the standard library. diff --git a/reference/promise-types/packages.markdown b/reference/promise-types/packages.markdown index cbce8d15f..f8ef68a24 100644 --- a/reference/promise-types/packages.markdown +++ b/reference/promise-types/packages.markdown @@ -2,7 +2,6 @@ layout: default title: packages published: true -tags: [reference, bundle agent, packages, packages promises, promise types] --- CFEngine 3.7 and later supports package management through a simple promise @@ -17,7 +16,7 @@ does not currently cover. To read about the old package promise, go to the [old package promise section][packages (deprecated)]. The actual communication with the package manager on the system is handled by so -called [package modules][Package Modules], which are specifically written for +called [package modules][Package modules], which are specifically written for each type of package manager. In this example, we want the software package "apache2" to be present on the @@ -202,10 +201,10 @@ packages: The package module body you wish to use for the package promise. The default is platform dependent, see [`package_module`][Components#package_module] in Components -and Common Control. The name of the body is expected to be the same as the name +and Common control. The name of the body is expected to be the same as the name of the package module inside `/var/cfengine/modules/packages`. -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### default_options @@ -252,11 +251,11 @@ body package_module apt_get ``` **Note for `package_module` authors**: -[`list-installed`][Package Modules#list-installed] will be called when the agent +[`list-installed`][Package modules#list-installed] will be called when the agent repairs a package using the given `package_module`, when the lock has expired or when the agent is run without locks. -**See also:** `Package Modules` +**See also:** `Package modules` #### query_updates_ifelapsed @@ -285,12 +284,12 @@ body package_module apt_get ``` **Note for `package_module` authors**: -[`list-updates`][Package Modules#list-updates] will be called when the lock has +[`list-updates`][Package modules#list-updates] will be called when the lock has expired or when the agent is run without locks. -[`list-updates-local`][Package Modules#list-updates-local] is called in all +[`list-updates-local`][Package modules#list-updates-local] is called in all other conditions. -**See also:** `Package Modules` +**See also:** `Package modules` #### interpreter @@ -315,7 +314,7 @@ body package_module apt_get } ``` -**See also:** `Package Modules` +**See also:** `Package modules` **History:** Introduced in 3.13.0, 3.12.2 @@ -343,14 +342,14 @@ body package_module yum_all_repos } ``` -**See also:** `Package Modules` +**See also:** `Package modules` **History:** Introduced in 3.13.0, 3.12.2 ## Package modules out-of-the-box ### yum -Manage packages using ```yum```. This is the [default package module](lib/packages.cf#package_module_knowledge) for Red Hat, CentOS and Amazon Linux. +Manage packages using ```yum```. This is the [default package module][lib/packages.cf#package_module_knowledge] for Red Hat, CentOS and Amazon Linux. **Examples:** @@ -617,7 +616,7 @@ packages: ### snap -Manage packages using [snap](https://en.wikipedia.org/wiki/Snappy_(package_manager)). +Manage packages using [snap](https://en.wikipedia.org/wiki/Snappy_%28package_manager%29). ```cf3 bundle agent main diff --git a/reference/promise-types/processes.markdown b/reference/promise-types/processes.markdown index c341d06b1..5a590d9c0 100644 --- a/reference/promise-types/processes.markdown +++ b/reference/promise-types/processes.markdown @@ -2,7 +2,6 @@ layout: default title: processes published: true -tags: [reference, bundle agent, promise types, processes, processes promises, promise types] --- Process promises refer to items in the system process table, i.e., a command in @@ -99,7 +98,7 @@ commands: **Type:** `body process_count` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### in_range_define @@ -168,7 +167,7 @@ out_of_range_define => { "process_anomaly", "anomaly_$(s)"}; **Type:** `body process_select` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### command diff --git a/reference/promise-types/reports.markdown b/reference/promise-types/reports.markdown index 2880c9e10..9d4e08a73 100644 --- a/reference/promise-types/reports.markdown +++ b/reference/promise-types/reports.markdown @@ -2,7 +2,6 @@ layout: default title: reports published: true -tags: [reference, bundle common, reports, promises] --- Reports promises simply print messages. Outputting a message without @@ -91,7 +90,7 @@ and has no effect. Deprecated in CFEngine 3.4. **Type:** `body printfile` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### file_to_print diff --git a/reference/promise-types/roles.markdown b/reference/promise-types/roles.markdown index 0fa7998e1..e2667f9b3 100644 --- a/reference/promise-types/roles.markdown +++ b/reference/promise-types/roles.markdown @@ -2,7 +2,6 @@ layout: default title: roles published: true -tags: [reference, bundle server, cf-serverd, cf-runagent, access control, users, roles, server, promise types] --- Roles promises are server-side decisions about which users are allowed @@ -37,13 +36,15 @@ roles: ``` In this example user `mark` is granted permission to remotely activate -classes matching the regular expression `Myclass_.*` hen using the +classes matching the regular expression `Myclass_.*` when using the `cf-runagent` to activate CFEngine. **** ## Attributes ## +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + ### authorize **Description:** List of public-key user names that are allowed to activate diff --git a/reference/promise-types/services.markdown b/reference/promise-types/services.markdown index ce9c53fca..20d243587 100644 --- a/reference/promise-types/services.markdown +++ b/reference/promise-types/services.markdown @@ -2,7 +2,6 @@ layout: default title: services published: true -tags: [reference, bundle agent, services, processes, services promises, promise types] --- `services` type promises in their simplest *generic* form are an abstraction on @@ -58,10 +57,9 @@ body service_method winmethod **Notes:** -Services promises for Windows are only available in CFEngine Enterprise. Note -that the name of a service in Windows may be different from its ```Display -name```. CFEngine Enterprise policies use the name, not the display name, -due to the need for uniqueness. +Services promises for Windows are only available in CFEngine Enterprise. +Note that the name of a service in Windows may be different from its **Display name**. +CFEngine Enterprise policies use the name, not the display name, due to the need for uniqueness. ![WinService](promise-types-services-winservice-properties_name.png) @@ -107,7 +105,7 @@ services: service_method => service_test; "$(mail)" service_policy => "stop", - service_method => service_test; + service_method => service_test; } body service_method service_test @@ -156,29 +154,15 @@ standard library. **Allowed input range:** (arbitrary string)|(menu_option) depending on `service_type` -* When `service_type` is `windows` allowed values are limited to `start`, - `stop`, `enable`, or `disable`. - - * **start|enable** :: Will start the service if it is not running. ```Startup - Type``` will be set to ```Manual``` if it is not ```Automatic``` or - ```Automatic (Delayed Start)```. For a service to be configured to start - automatically on boot a `service_method` must be declared and - `service_autostart_policy` must be set to ```boot_time```. - - * **stop** :: Will stop the service if it is running. ```Startup Type``` will - not be modified unless a `service_method` is declared and - `service_autostart_policy` is set. - - * **disable** :: Will stop the service if it is running, and ```Startup Type``` - will be set to ```Disabled```. - - -* When `service_type` is ```generic``` any string is allowed and - `service_bundle` is responsible for interpreting and implementing the desired - state based on the `service_policy` value. - - Historically `service_type` ```generic``` has supported ```start```, - ```stop```, ```enable```, ```disable```, ```restart``` and ```reload```. +* When `service_type` is `windows` allowed values are limited to `start`, `stop`, `enable`, or `disable`. + * **start|enable** :: Will start the service if it is not running. + **Startup Type** will be set to **Manual** if it is not **Automatic** or **Automatic (Delayed Start)**. + For a service to be configured to start automatically on boot a `service_method` must be declared and `service_autostart_policy` must be set to `boot_time`. + * **stop** :: Will stop the service if it is running. **Startup Type** will not be modified unless a `service_method` is declared and `service_autostart_policy` is set. + * **disable** :: Will stop the service if it is running, and **Startup Type** + will be set to **Disabled**. +* When `service_type` is `generic` any string is allowed and `service_bundle` is responsible for interpreting and implementing the desired state based on the `service_policy` value. + Historically `service_type` `generic` has supported `start`, `stop`, `enable`, `disable`, `restart` and `reload`. **Example:** @@ -315,7 +299,7 @@ and `$(this.service_policy)` (the policy state the service should have). **Notes:** `service_bundle` is not used when `service_type` is ```windows```. -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### service_args diff --git a/reference/promise-types/storage.markdown b/reference/promise-types/storage.markdown index 9fa6aa104..19298c58c 100644 --- a/reference/promise-types/storage.markdown +++ b/reference/promise-types/storage.markdown @@ -2,7 +2,6 @@ layout: default title: storage published: true -tags: [reference, bundle agent, storage, storage promises, mount, filesystem, disks] --- Storage promises refer to disks and filesystem properties. @@ -56,7 +55,7 @@ body mount nfs(server,source) **Type:** `body mount` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### edit_fstab @@ -180,7 +179,7 @@ unmount => "true"; **Type:** `body volume` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### check_foreign diff --git a/reference/promise-types/users.markdown b/reference/promise-types/users.markdown index 33d65ff8c..40bf0f1b1 100644 --- a/reference/promise-types/users.markdown +++ b/reference/promise-types/users.markdown @@ -2,7 +2,6 @@ layout: default title: users published: true -tags: [reference, bundle agent, cf-agent, users, promise types] --- User promises are promises made about **local users** on a host. They @@ -205,7 +204,7 @@ body password user_password } ``` -**See also:** [Common Body Attributes][Promise Types#Common Body Attributes] +**See also:** [Common body attributes][Promise types#Common body attributes] #### format diff --git a/reference/promise-types/vars.markdown b/reference/promise-types/vars.markdown index 2c16ee2c5..bb42be062 100644 --- a/reference/promise-types/vars.markdown +++ b/reference/promise-types/vars.markdown @@ -2,7 +2,6 @@ layout: default title: vars published: true -tags: [reference, bundle common, vars, promises] --- [Variables][variables] in CFEngine are defined @@ -14,7 +13,7 @@ The allowed characters in variable names are alphanumeric (both upper and lower and underscore. `Associative` arrays using the string type and square brackets `[]` to enclose an arbitrary key are being deprecated in favor of the `data` variable type. -## Scalar Variables +## Scalar variables ### string @@ -304,6 +303,8 @@ vars: ## Attributes ## +{{< CFEngine_include_markdown(common-attributes.include.markdown) >}} + ### policy **Description:** The policy for (dis)allowing (re)definition of variables @@ -378,7 +379,7 @@ two_example_com:: comment => "Define a global domain for hosts in the two.example.com domain"; ``` -(Promises within the same bundle are evaluated top to bottom, so vars promises further down in a bundle can overwrite previous values of a variable. See [**normal ordering**][Normal Ordering] for more information). +(Promises within the same bundle are evaluated top to bottom, so vars promises further down in a bundle can overwrite previous values of a variable. See [**normal ordering**][Normal ordering] for more information). ## Defining variables in foreign bundles diff --git a/reference/special-variables.markdown b/reference/special-variables.markdown index e9dda7e03..29bb1808b 100644 --- a/reference/special-variables.markdown +++ b/reference/special-variables.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Special Variables +title: Special variables published: true sorting: 50 -tags: [reference, variables] --- Variables are promises that can be defined in any promise bundle. Users can create their diff --git a/reference/special-variables/connection.markdown b/reference/special-variables/connection.markdown index b5acc7117..253b45da8 100644 --- a/reference/special-variables/connection.markdown +++ b/reference/special-variables/connection.markdown @@ -2,7 +2,6 @@ layout: default title: connection published: true -tags: [reference, variables, connection] --- The context `connection` is used by the `shortcut` attribute in `access` diff --git a/reference/special-variables/const.markdown b/reference/special-variables/const.markdown index 335849a1b..0937888ff 100644 --- a/reference/special-variables/const.markdown +++ b/reference/special-variables/const.markdown @@ -2,7 +2,6 @@ layout: default title: const published: true -tags: [reference, variables, const, const] --- CFEngine defines a number of variables for embedding unprintable values diff --git a/reference/special-variables/def.markdown b/reference/special-variables/def.markdown index 4e1e30872..a8aa32652 100644 --- a/reference/special-variables/def.markdown +++ b/reference/special-variables/def.markdown @@ -2,7 +2,6 @@ layout: default title: def published: true -tags: [reference, variables, def, augments] --- The context `def` is populated by the diff --git a/reference/special-variables/edit.markdown b/reference/special-variables/edit.markdown index 989729a5c..4b0dffaee 100644 --- a/reference/special-variables/edit.markdown +++ b/reference/special-variables/edit.markdown @@ -2,7 +2,6 @@ layout: default title: edit published: true -tags: [reference, variables, edit, edit_line, files promises] --- This context is used to access information about editing promises during diff --git a/reference/special-variables/match.markdown b/reference/special-variables/match.markdown index 23411d324..23b9d2d31 100644 --- a/reference/special-variables/match.markdown +++ b/reference/special-variables/match.markdown @@ -2,7 +2,6 @@ layout: default title: match published: true -tags: [reference, variables, match, strings, file editing, files promises, edit_line] --- Each time CFEngine matches a string, these values are assigned to a special diff --git a/reference/special-variables/mon.markdown b/reference/special-variables/mon.markdown index 64efcfae0..126ff27c2 100644 --- a/reference/special-variables/mon.markdown +++ b/reference/special-variables/mon.markdown @@ -2,7 +2,6 @@ layout: default title: mon published: true -tags: [reference, variables, mon, cf-monitord, monitoring] --- The variables discovered by `cf-monitord` are placed in this monitoring diff --git a/reference/special-variables/sys.markdown b/reference/special-variables/sys.markdown index 9b96527c0..87f5a3370 100644 --- a/reference/special-variables/sys.markdown +++ b/reference/special-variables/sys.markdown @@ -2,7 +2,6 @@ layout: default title: sys published: true -tags: [reference, variables, sys, discovery, system, inventory] --- System variables are derived from CFEngine's automated discovery of system @@ -257,7 +256,7 @@ reports: "Tell me $(sys.hardware_mac[eth0])"; ``` -**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-3224](https://tracker.mender.io/browse/CFE-3224). +**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-4174](https://northerntech.atlassian.net/browse/CFE-4174). **History:** Was introduced in 3.3.0, Enterprise 2.2.0 (2011) @@ -983,7 +982,7 @@ e.g. `$(sys.ip2iface[1.2.3.4])`. from any of the other associative arrays). Only those interfaces which are marked as "up" and have an IP address will have entries. -- The *values* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be `wlan0_1`. Ref: [CFE-3224](https://tracker.mender.io/browse/CFE-3224). +- The *values* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be `wlan0_1`. Ref: [CFE-4174](https://northerntech.atlassian.net/browse/CFE-4174). **History:** Was introduced in 3.9. @@ -1032,19 +1031,19 @@ are marked as "up" and have an IP address will be listed. The first octet of the IPv4 address of the system interface named as the associative array index, e.g. `$(ipv4_1[le0])` or `$(ipv4_1[xr1])`. -**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-3224](https://tracker.mender.io/browse/CFE-3224). +**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-4174](https://northerntech.atlassian.net/browse/CFE-4174). ### sys.ipv4_2[interface_name] The first two octets of the IPv4 address of the system interface named as the associative array index, e.g. `$(ipv4_2[le0])` or `$(ipv4_2[xr1])`. -**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-3224](https://tracker.mender.io/browse/CFE-3224). +**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-4174](https://northerntech.atlassian.net/browse/CFE-4174). ### sys.ipv4_3[interface_name] The first three octets of the IPv4 address of the system interface named as the associative array index, e.g. `$(ipv4_3[le0])` or `$(ipv4_3[xr1])`. -**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-3224](https://tracker.mender.io/browse/CFE-3224). +**Note:** The *keys* in this array are [canonified][canonify]. For example, the entry for `wlan0.1` would be found under the `wlan0_1` key. Ref: [CFE-4174](https://northerntech.atlassian.net/browse/CFE-4174). ### sys.key_digest diff --git a/reference/special-variables/this.markdown b/reference/special-variables/this.markdown index 940f7d507..f355954c7 100644 --- a/reference/special-variables/this.markdown +++ b/reference/special-variables/this.markdown @@ -2,7 +2,6 @@ layout: default title: this published: true -tags: [reference, variables, this, this] --- The context `this` is used to access information about promises during @@ -74,8 +73,8 @@ attributes: * `edit_template` * [`source`][files#source] in `copy_from` * `exec_program` in `file_select` -* class names in [`body classes`][Promise Types#classes] -* logging attributes in [`body action`][Promise Types#action] +* class names in [`body classes`][Promise types#classes] +* logging attributes in [`body action`][Promise types#action] * promised service name in `service_method` For example: diff --git a/release-notes.markdown b/release-notes.markdown index 85619bdd1..9952a17ba 100644 --- a/release-notes.markdown +++ b/release-notes.markdown @@ -1,16 +1,15 @@ --- layout: default -title: Release Notes +title: Release notes published: true sorting: 30 -tags: [overviews, releases, latest release, platforms, versions] --- * [New in CFEngine][New in CFEngine] Learn about the newest features in CFEngine {{site.cfengine.branch}} -* [Supported Platforms and Versions][Supported Platforms and Versions] +* [Supported platforms and versions][Supported platforms and versions] These are the supported platforms for the current release. -* [Known Issues][Known Issues] +* [Known issues][Known issues] View any issues of which we are currently aware and investigating. View possible workarounds. diff --git a/release-notes/known-issues.markdown b/release-notes/known-issues.markdown index 7a48489c7..2ce106e52 100644 --- a/release-notes/known-issues.markdown +++ b/release-notes/known-issues.markdown @@ -1,23 +1,22 @@ --- layout: default -title: Known Issues +title: Known issues sorting: 50 published: true -tags: [overviews, releases, latest release, platforms, versions, known issues] --- CFEngine defects are managed in our [bug tracker][bug tracker]. Please report bugs or unexpected behavior there, following the documented guideline for new bug reports. -* Core Issues affecting [{{site.cfengine.branch}}](https://tracker.mender.io/secure/QuickSearch.jspa?searchString=v:{{site.cfengine.branch}}*) +* Core Issues affecting [{{site.cfengine.branch}}](https://northerntech.atlassian.net/secure/QuickSearch.jspa?searchString=v:{{site.cfengine.branch}}*) The items below highlight issues that require additional awareness when starting with CFEngine or when upgrading from a previous version. ### `cf-agent -N` or `cf-agent --negate` is not working -As reported in [CFE-1589](https://tracker.mender.io/browse/CFE-1589) the +As reported in [CFE-1589](https://northerntech.atlassian.net/browse/CFE-1589) the functionality of negating persistent classes on the command line, was removed sometime before 3.5, commit cf63db27945f0628caa5bf45338f7709d5d12b21. The ticket is open until the @@ -77,7 +76,7 @@ ERROR - 2016-06-15 07:24:15 --> Severity: Warning --> readfile(https://myhostnam The solution is to generate a new certificate with the correct CN, i.e. the one you use to access the CFEngine Server. To see how to do -this, look at the documentation for using a [Custom SSL certificate][Custom SSL Certificate]. +this, look at the documentation for using a [Custom SSL certificate][Custom SSL certificate]. ### Enterprise software inventory is not out-of-the-box diff --git a/release-notes/legal-and-licenses.markdown b/release-notes/legal-and-licenses.markdown new file mode 100644 index 000000000..6039938ed --- /dev/null +++ b/release-notes/legal-and-licenses.markdown @@ -0,0 +1,118 @@ +--- +layout: default +title: Legal and licenses +published: true +sorting: 999 +alias: legal.html +--- + +## General legal disclaimer + +Please note that unless otherwise noted (through a customer agreement or similar) +CFEngine is offered on an "as is" basis without warranty of +any kind, and that our products are not error or bug free. To the maximum +extent permitted by applicable law, CFEngine on behalf of itself and its +suppliers, disclaims all warranties and conditions, either express or implied, +including, but not limited to, implied warranties of merchantability, fitness +for a particular purpose, title and non-infringement with regard to the +Licensed Software. + +## CFEngine documentation license + +The documentation is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](https://creativecommons.org/licenses/by-sa/3.0/deed.en_US). + +## 3rd party licenses and libraries + +CFEngine includes the following 3rd party libraries and components: + +### Common dependencies + +These dependencies are used by both CFEngine Community (Open Source) as well as CFEngine Enterprise: + +* [libacl](https://savannah.nongnu.org/projects/acl) under the [LGPL](https://git.savannah.gnu.org/cgit/acl.git/tree/include/acl.h) license +* [libattr](https://savannah.nongnu.org/projects/attr) under the [LGPL](https://git.savannah.gnu.org/cgit/attr.git/tree/include/libattr.h) license +* [libcurl](https://curl.se) under the [MIT/X derivative license](https://curl.se/docs/copyright.html) +* [libiconv](http://ftp.gnu.org/gnu/libiconv/) under the [LGPL](https://git.savannah.gnu.org/gitweb/?p=libiconv.git;a=blob;f=include/iconv.h.in) license +* [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/FAQ) under the [MIT license](https://opensource.org/license/mit/) +* [libyaml](https://pyyaml.org/wiki/LibYAML) under the [MIT license](https://github.com/yaml/libyaml/blob/master/License) +* [diffutils](https://ftpmirror.gnu.org/diffutils/) under the [GPLv3](https://git.savannah.gnu.org/cgit/diffutils.git/tree/src/diff.c) +* [LMDB](https://www.symas.com/lmdb) under the [OpenLDAP Public License](https://www.openldap.org/software/release/license.html) +* [OpenSSL](https://www.openssl.org) under the [OpenSSL (OpenSSL 1) or Apache v2 (OpenSSL 3) license](https://www.openssl.org/source/license.html) +* [PCRE](https://www.pcre.org) under the [PCRE license](https://www.pcre.org/licence.txt) or + [PCRE2](https://pcre2project.github.io/pcre2/) under the [PCRE2 + license](https://github.com/PCRE2Project/pcre2/blob/master/LICENCE) +* [PEG](https://piumarta.com/software/peg/) under the [MIT license](https://opensource.org/license/mit/) +* [zlib](https://www.zlib.net) under the [zlib license](https://www.zlib.net/zlib_license.html) + +### Enterprise only dependencies + +In addition to the common dependencies listed above, these dependencies are specific to CFEngine Enterprise: + +* [Angular.js](https://angularjs.org) under the [MIT license](https://github.com/angular/angular.js/blob/master/LICENSE) +* [Apache](https://httpd.apache.org) under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) +* [APR and APR-util](https://apr.apache.org) under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) +* [Chosen](https://harvesthq.github.io/chosen/) under the [MIT license](https://github.com/harvesthq/chosen/blob/master/LICENSE.md) +* [CodeIgniter](https://github.com/bcit-ci/CodeIgniter/) under the [MIT license](https://github.com/bcit-ci/CodeIgniter/blob/develop/license.txt) +* [Disphelper](https://disphelper.sourceforge.net) (only Windows) under the [BSD license](https://opensource.org/licenses/bsd-license.php) +* [Flot](https://www.flotcharts.org/) under the [MIT license](https://github.com/flot/flot/blob/master/LICENSE.txt) +* [Font Awesome](https://fontawesome.com/) by Dave Gandy - https://fontawesome.io/license/ +* [git](https://git-scm.com) under the [GNU General Public License, version 2 (GPLv2)](https://opensource.org/licenses/GPL-2.0) +* [Glyphicons](https://glyphicons.com/license/) under [Creative Commons Attribution 3.0 Unported (CC BY 3.0)](https://creativecommons.org/licenses/by-sa/3.0/deed.en_US) +* [HighCharts](https://www.highcharts.com/) under the [OEM license by HighSoft](https://shop.highcharts.com/) +* [jQuery](https://jquery.com/) under the [MIT license](https://opensource.org/license/mit/) +* [libexpat](https://sourceforge.net/projects/expat/) under the [MIT license](https://opensource.org/license/mit/) +* [libgnurx](http://www.gnu.org/software/rx/rx.html) under the [LGPLv2.1](https://github.com/TimothyGu/libgnurx/blob/libgnurx-2.5.1/regex.h) license +* [mod_ssl](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html) under a [BSD style license](http://www.modssl.org/docs/2.8/ssl_overview.html) +* [oauth2-server-php](https://github.com/bshaffer/oauth2-server-php) under the [MIT license](https://github.com/bshaffer/oauth2-server-php/blob/develop/LICENSE) +* [OpenLDAP and liblber](https://www.openldap.org) under the [OpenLDAP Public License](https://www.openldap.org/software/release/license.html) +* [PHP](https://php.net) under the [PHP license](https://www.php.net/license/3_01.txt) +* [PostgreSQL](https://www.postgresql.org) under the [PostgreSQL License](https://opensource.org/licenses/postgresql) +* [rsync](https://rsync.samba.org) under the [GPLv3](https://rsync.samba.org/GPL.html) +* [Twitter Bootstrap Framework](https://getbootstrap.com) under [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) +* [Bootstrap Icons](https://icons.getbootstrap.com) under the [MIT license](https://github.com/twbs/icons/blob/main/LICENSE) +* [underscore.js](https://underscorejs.org) under the [MIT license](https://opensource.org/license/mit/) +* [ace-builds](https://github.com/ajaxorg/ace-builds) under the [BSD-3-Clause](https://github.com/ajaxorg/ace-builds/blob/master/LICENSE) license +* [angular](http://angularjs.org) under the [MIT](https://github.com/angular/angular.js/blob/master/LICENSE) license +* [angular-chosen-localytics](http://github.com/leocaseiro/angular-chosen) under the [MIT](https://github.com/leocaseiro/angular-chosen/blob/master/LICENSE) license +* [angular-daterangepicker](https://github.com/fragaria/angular-daterangepicker) under the [MIT](https://github.com/fragaria/angular-daterangepicker/blob/master/LICENSE.md) license +* [angular-ui](https://github.com/buildium/angular-ui) under the [MIT](https://github.com/buildium/angular-ui/blob/master/LICENSE) license +* [bootstrap-multiselect](http://davidstutz.github.io/bootstrap-multiselect/) under the [Apache License, Version 2.0](http://davidstutz.github.io/bootstrap-multiselect/#license) +* [bootstrap-tour](http://bootstraptour.com) under the [MIT](https://github.com/sorich87/bootstrap-tour/blob/master/LICENSE) license +* [chosen-js](https://harvesthq.github.io/chosen/) under the [MIT](https://github.com/harvesthq/chosen/blob/master/LICENSE.md) license +* [clipboard](https://clipboardjs.com) under the [MIT](https://github.com/zenorocha/clipboard.js/blob/master/LICENSE) license +* [datatables](http://datatables.net) under the [MIT](https://datatables.net/license/mit) license +* [daterangepicker](https://github.com/dangrossman/daterangepicker) under the [MIT](https://github.com/dangrossman/daterangepicker/blob/master/README.md#license) license +* [google-code-prettify](https://www.npmjs.com/package/google-code-prettify) under the [Apache License 2.0](https://github.com/googlearchive/code-prettify/blob/master/COPYING) +* [highcharts](http://www.highcharts.com) under the [SLA](https://shop.highcharts.com/license) license +* [html5shiv](https://github.com/aFarkas/html5shiv#readme) under the [MIT license and GPL2](https://github.com/aFarkas/html5shiv/blob/master/MIT%20and%20GPL2%20licenses.md) +* [ip-subnet-calculator](https://github.com/franksrevenge/IPSubnetCalculator) under the [MIT](https://github.com/salieri/IPSubnetCalculator/blob/master/LICENSE) license +* [jquery](https://jquery.com) under the [MIT](https://github.com/salieri/IPSubnetCalculator/blob/master/LICENSE) license +* [jquery-appear-original](https://github.com/morr/jquery.appear) under the [MIT](https://github.com/morr/jquery.appear/blob/master/LICENSE) license +* [jquery-form](https://github.com/jquery-form/form) under the [MIT](https://github.com/jquery-form/form/blob/master/LICENSE) license +* [jquery-multiselect](https://github.com/techhysahil/jquery-MultiSelect) under the [MIT](https://github.com/techhysahil/jquery-MultiSelect/blob/master/LICENSE) license +* [jquery-ui-timepicker-addon](http://trentrichardson.com/examples/timepicker) under the [MIT](https://github.com/trentrichardson/jQuery-Timepicker-Addon?tab=License-1-ov-file) license +* [jquery-validation](https://jqueryvalidation.org/) under the [MIT](https://github.com/jquery-validation/jquery-validation/blob/master/LICENSE.md) license +* [jquery-wheelcolorpicker](https://raffer.one/projects/jquery-wheelcolorpicker) under the [MIT](https://github.com/fujaru/jquery-wheelcolorpicker/blob/master/LICENSE) license +* [jquery.cookie](https://github.com/carhartl/jquery-cookie) under the [MIT](https://github.com/carhartl/jquery-cookie/blob/master/MIT-LICENSE.txt) license +* [jquery.flot](https://www.npmjs.com/package/jquery.flot) under the [MIT](https://github.com/flot/flot/blob/master/LICENSE.txt) license +* [json2](http://github.com/SamuraiJack/JSON2/tree) under the [GNU Lesser General Public License](https://github.com/canonic-epicure/JSON2/blob/master/README.md#copyright-and-license) +* [jstimezonedetect](https://github.com/pellepim/jstimezonedetect) under the [MIT](https://github.com/pellepim/jstimezonedetect/blob/master/LICENCE.txt) license +* [notifyjs](https://notifyjs.jpillora.com/) under the [MIT](https://github.com/jpillora/notifyjs/blob/master/LICENSE) license +* [pluralize](https://github.com/blakeembrey/pluralize) under the [MIT](https://github.com/plurals/pluralize/blob/master/LICENSE) license +* [zxcvbn](https://github.com/dropbox/zxcvbn) under the [MIT](https://github.com/dropbox/zxcvbn/blob/master/LICENSE.txt) license +* [FPDF](http://www.fpdf.org/) under the [permissive license](https://github.com/Setasign/FPDF/blob/master/license.txt) +* [guzzle](https://docs.guzzlephp.org/) under the [MIT](https://docs.guzzlephp.org/en/stable/overview.html#license) license +* [tcpdf](https://tcpdf.org/) under the [GNU LESSER GENERAL PUBLIC LICENSE](https://tcpdf.org/docs/license/) +* [Slim](https://www.slimframework.com/) under the [MIT](https://github.com/slimphp/Slim/blob/4.x/LICENSE.md) +* [monolog](https://seldaek.github.io/monolog/) under the [MIT](https://github.com/Seldaek/monolog/blob/master/LICENSE) +* [LdapRecord](https://ldaprecord.com/) under the [MIT](https://github.com/DirectoryTree/LdapRecord/blob/master/license.md) +* [phpseclib](https://phpseclib.com/) under the [MIT](https://github.com/phpseclib/phpseclib/blob/master/LICENSE) +* [tonic](http://peej.github.com/tonic/) under the [MIT](https://github.com/peej/tonic/blob/master/LICENSE) + +### Optional, non-default dependencies + +These dependencies are not a part of the packages we build and distribute, but specific users or customers may build CFEngine with support for custom functionality and with custom software dependencies: + +* [libvirt](https://libvirt.org/) under the [LGPL version 2.1](https://www.opensource.org/licenses/lgpl-license.html) +* [QDBM](https://sourceforge.net/projects/qdbm/) under the [GNU Library or Lesser General Public License 2.0 (LGPLv2)](https://opensource.org/license/lgpl-2-1/) +* [TokyoCabinet](https://github.com/hthetiot/Tokyo-Cabinet) under the [GNU Lesser General Public License](https://www.opensource.org/licenses/lgpl-license.html) diff --git a/release-notes/supported-platforms.markdown b/release-notes/supported-platforms.markdown index da5752134..5432d14f2 100644 --- a/release-notes/supported-platforms.markdown +++ b/release-notes/supported-platforms.markdown @@ -1,9 +1,8 @@ --- layout: default -title: Supported Platforms and Versions +title: Supported platforms and versions sorting: 20 published: true -tags: [overviews, releases, latest release, platforms, versions, support] --- CFEngine works on a wide range of platforms, and the CFEngine team strives to @@ -11,32 +10,35 @@ provide support for the platforms most frequently used by our users. CFEngine provides [binary packages of the Enterprise edition][enterprise software download page] for all supported platforms and [binary packages for popular Linux distributions for the Community edition][community download page]. -## Enterprise Server ## +## Hub -| Platform | Versions | Architecture | -| :--------------: | :------------------: | :---------------: | -| CentOS/RHEL | 7, 8.1+ | x86-64 | -| Debian | 9, 10 | x86-64 | -| Ubuntu | 16.04, 18.04, 20.04 | x86-64 | +| Platform | Versions | Architecture | +|:-----------:|:---------------------------------:|:------------:| +| CentOS/RHEL | 7, 8.1+, 9 | x86-64 | +| Debian | 9, 10, 11, 12 | x86-64 | +| Debian | 11, 12 | arm64 | +| Ubuntu | 16.04, 18.04, 20.04, 22.04, 24.04 | x86-64 | +| Ubuntu | 22.04, 24.04 | arm64 | Any supported host can be a policy server in Community installations of CFEngine. -## Hosts ## +## Clients -| Platform | Versions | Architectures | -| :---------: | :-----------------: | :-------------: | -| AIX | 7.1, 7.2 | PowerPC | -| CentOS/RHEL | 6, 7, 8.1 | x86-64 | -| Debian | 9, 10 | x86-64 | -| HP-UX | 11.31+ | Itanium | -| SLES | 11, 12, 15 | x86-64 | -| Solaris | 11 | UltraSparc | -| Solaris | 10 | UltraSparc, x86 | -| Ubuntu | 16.04, 18.04, 20.04 | x86-64 | -| Windows | 2012, 2016, 2019 | x86-64, x86 | +| Platform | Versions | Architectures | +|:-----------:|:--------------------------------:|:-------------:| +| AIX | 7.1, 7.2 | PowerPC | +| CentOS/RHEL | 6, 7, 8.1+, 9 | x86-64 | +| Debian | 9, 10, 11, 12 | x86-64 | +| Debian | 11, 12 | arm64 | +| HP-UX | 11.31+ | Itanium | +| SLES | 12, 15 | x86-64 | +| Solaris | 11 | UltraSparc | +| Ubuntu | 16.04 18.04, 20.04, 22.04, 24.04 | x86-64 | +| Ubuntu | 22.04, 24.04 | arm64 | +| Windows | 2012, 2016, 2019 | x86-64, x86 | -[Known Issues][] also includes platform-specific notes. +[Known issues][] also includes platform-specific notes. CFEngine Enterprise has [Virtual I/O Server (VIOS) Recognized status](http://www.ibm.com/partnerworld/gsd/solutiondetails.do?solution=48493) from IBM. diff --git a/release-notes/whatsnew.markdown b/release-notes/whatsnew.markdown index 75486d410..94580d30e 100644 --- a/release-notes/whatsnew.markdown +++ b/release-notes/whatsnew.markdown @@ -3,11 +3,10 @@ layout: default title: New in CFEngine published: true sorting: 10 -tags: [what's new] --- See what's new in this release. -* [Core Changelog][Changelog] -* [Enterprise Changelog][Enterprise Changelog] -* [Masterfiles Changelog][Masterfiles Changelog] +* [Core changelog][Changelog] +* [Enterprise changelog][Enterprise changelog] +* [Masterfiles changelog][Masterfiles changelog] diff --git a/release-notes/whatsnew/changelog-core.markdown b/release-notes/whatsnew/changelog-core.markdown index 09f38ac57..48b1b911d 100644 --- a/release-notes/whatsnew/changelog-core.markdown +++ b/release-notes/whatsnew/changelog-core.markdown @@ -1,12 +1,11 @@ --- layout: default -title: ChangeLog +title: Changelog published: true sorting: 10 -tags: [what's new] --- -**See also:** [Enterprise Changelog][Enterprise Changelog], [Masterfiles Changelog][Masterfiles Changelog] +**See also:** [Enterprise changelog][Enterprise changelog], [Masterfiles changelog][Masterfiles changelog]
       {% raw %}
      diff --git a/release-notes/whatsnew/changelog-enterprise.markdown b/release-notes/whatsnew/changelog-enterprise.markdown
      index 88f4d9778..7e16a9ff0 100644
      --- a/release-notes/whatsnew/changelog-enterprise.markdown
      +++ b/release-notes/whatsnew/changelog-enterprise.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Enterprise ChangeLog
      +title: Enterprise changelog
       published: true
       sorting: 30
      -tags: [what's new, enterprise]
       ---
       
      -**See also:** [Core Changelog][Changelog], [Masterfiles Changelog][Masterfiles Changelog]
      +**See also:** [Core changelog][Changelog], [Masterfiles changelog][Masterfiles changelog]
       
       
       {% raw %}
      diff --git a/release-notes/whatsnew/changelog-masterfiles-policy-framework.markdown b/release-notes/whatsnew/changelog-masterfiles-policy-framework.markdown
      index 15667d527..66fa88380 100644
      --- a/release-notes/whatsnew/changelog-masterfiles-policy-framework.markdown
      +++ b/release-notes/whatsnew/changelog-masterfiles-policy-framework.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Masterfiles ChangeLog
      +title: Masterfiles changelog
       published: true
       sorting: 20
      -tags: [what's new, MPF, masterfiles]
       ---
       
      -**See also:** [Core Changelog][Changelog], [Enterprise Changelog][Enterprise Changelog]
      +**See also:** [Core changelog][Changelog], [Enterprise changelog][Enterprise changelog]
       
       
       {% raw %}
      diff --git a/resources/additional-topics.markdown b/resources/additional-topics.markdown
      index 2e8c967ef..c4f60b940 100644
      --- a/resources/additional-topics.markdown
      +++ b/resources/additional-topics.markdown
      @@ -3,5 +3,4 @@ layout: default
       title: Additional topics
       published: true
       sorting: 20
      -tags: [overviews, enterprise, REST, API, reporting]
       ---
      diff --git a/resources/additional-topics/agility.markdown b/resources/additional-topics/agility.markdown
      index bbbfa9215..138afeec4 100644
      --- a/resources/additional-topics/agility.markdown
      +++ b/resources/additional-topics/agility.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: Agility
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# Understanding Agility
      +## Understanding agility
       
       We intuitively recognize agility as the capability to respond rapidly enough and
       flexibly enough to a difficult challenge. If we imagine an animal surviving in
      @@ -35,7 +34,7 @@ associated with a lack of agility: a blow, a fall or a loss.
       * Comprehension
       * Efficiency
       
      -## What make agility possible?
      +### What make agility possible?
       
       
       To understand agility, we have to understand time and the capacity for change.
      @@ -62,7 +61,7 @@ can help with this, if we adopt sound practices.
       Intuitively, we understand agility to be related to our capacity to respond to a
       situation. Let's try to pin this idea down more precisely.
       
      -## The capacity of a system
      +### The capacity of a system
       
       The capacity of a system is defined to be its maximum rate of change. Most
       often, this refers to speed of the system response to a single request1.
      @@ -70,7 +69,7 @@ often, this refers to speed of the system response to a single request1.
       In engineering, capacity is measured in changes per second, so it represents the
       maximum speed of a system within a single thread of activity2.
       
      -## Speed
      +### Speed
       
       Speed is the rate at which change takes place. For a configuration tool like
       CFEngine, speed can be measured either as
      @@ -160,7 +159,7 @@ agility. Remarkably this is usually unexpected for most practitioners, and most
       of system planning goes into first time deployment, rather than maintaining
       operational state.
       
      -## Precision
      +### Precision
       
       Acting quickly is not enough: we also need to be accurate in responding to
       change[^4]. We need to be able to:
      @@ -175,7 +174,7 @@ change[^4]. We need to be able to:
       Precision is maximized when:
       
       
      -* Changes are `precise', i.e. they can be made at a highly granular level,
      +* Changes are _precise_, i.e. they can be made at a highly granular level,
         without disturbing areas that are not relevant (few side-effects).
       
       * Policy is able to model or describe the desired state accurately, i.e. within
      @@ -195,7 +194,7 @@ Precision is maximized when:
       CFEngine is a fault tolerant system - it continues to work on what it can even
       when some parts of its model don't work out as expected[^6].
       
      -Next: Efficiency, Previous: Precision, Up: Understanding Agility
      +Next: Efficiency, Previous: Precision, Up: Understanding agility
       1.5 Comprehension
       
       The next challenge is concerns a human limitation. One of the greatest challenges in any organization lies in comprehending the system.
      @@ -212,7 +211,7 @@ Our ability to comprehend behaviour depends on how predictable it is, i.e. how w
       
       To keep the number of contexts to a minimum, CFEngine avoids mixing up what policy is being expressed with how the promises are kept. It uses a declarative language to separate the what from the how. This allows ordinary users to see what was intended without having to know the meaning of how, as was the case when scripting was used to configure systems.
       
      -Previous: Comprehension, Up: Understanding Agility
      +Previous: Comprehension, Up: Understanding agility
       1.6 Efficiency
       
       Finally, if we think about the efficiency of a configuration, which is another way of estimating its simplicity, we are interested in how much work it takes to represent our intentions. There are two ways we can think about efficiency: the efficiency of the automated process and the human efficiency in deploying it.
      @@ -241,7 +240,7 @@ General patterns play a role too in simplifying, because the reduce the number o
       
       Efficiency therefore plays a role in agility, because it affects the cost of change. Greater efficiency generally means greater speed, and more greater likelihood for precision.
       
      -Next: Agility in your work, Previous: Understanding Agility, Up: Top
      +Next: Agility in your work, Previous: Understanding agility, Up: Top
       2 Aspects of CFEngine that bring agility
       
       
      @@ -288,7 +287,7 @@ We can now summarize some qualities of CFEngine that favour agility:
       
       * Increasing system capacity - by scaling
       
      -## What agility means in different environments
      +### What agility means in different environments
       
       Let's examine some example cases where agility plays a role. Agility only has
       meaning relative to an environment, so in the following sections, we cite the
      @@ -301,12 +300,12 @@ that limber systems must prevail in IT's evolutionary jungle.
       * Desktop management
       * Web shops
       * Cloud providers
      -* High Performance Computing
      +* High performance computing
       * Government
       * Finance
       * Manufacturing
       
      -### Desktop management
      +#### Desktop management
       
       "The desktop space can be a very volatile environment, with multiple platforms."
       
      @@ -331,7 +330,7 @@ Precision:
       
           Desktop environments can involve many different platforms: Windows, multiple
           flavours of Linux and Macintosh, etc. A uniform low-cost way of
      -    `provisioning' and maintaining all of these, as well as responding to common
      +    _provisioning_ and maintaining all of these, as well as responding to common
           threats is of significant value.
       
           Precision is important to ensure that the resources made available are
      @@ -347,7 +346,7 @@ Precision:
           greatly reduce the time needed to return to the most current enterprise
           build.
       
      -### Web shops
      +#### Web shops
       
       Modern web-based companies often base their entire financial operations around
       an active web site. Down-time of the web service is mission critical.
      @@ -386,7 +385,7 @@ Precision:
           Customization and individuality is a large part of a website's business
           competitiveness. Maintaining precise
       
      -### Cloud providers
      +#### Cloud providers
       
       Speed:
       
      @@ -403,7 +402,7 @@ Precision:
           demand is probably the fastest rate of change.
       
       
      -### High Performance Computing
      +#### High performance computing
       
       High Performance clusters are typically found in the oil and gas industry, in
       movie, financial, weather and aviation industries, and any other modelling
      @@ -434,7 +433,7 @@ Precision:
           impossible to make a precise change when you don't fully comprehend the
           environment."
       
      -### Government
      +#### Government
       
       Speed:
       
      @@ -452,7 +451,7 @@ Precision:
           Finance is big money trying to make more big money. Government is focused
           more on compliance with its own regulations."
       
      -### Finance
      +#### Finance
       
       Speed:
       
      @@ -474,7 +473,7 @@ Precision:
           past, but this will have to change as the rest of the world's IT services
           accelerate.
       
      -### Manufacturing
      +#### Manufacturing
       
       SCADA (supervisory control and data acquisition) generally refers to industrial
       control systems (ICS): computer systems that monitor and control industrial,
      @@ -507,7 +506,7 @@ Precision:
           probe to detect microscopic fractures in the layers, one tool may just track
           it's position in line. Supply and demand, cost and revenue."
       
      -## Separating What from How (DevOps)
      +### Separating what from how (DevOps)
       
       
       If you have to designs a programmatic solution to a challenge, it will cost you
      @@ -519,11 +518,11 @@ carry-over from the era of 2nd Wave industrialization8.
       Think of CFEngine as an active knowledge management system, rather than as a
       relatively passive programming framework.
       
      -For `DevOps': programming is for your application, consider its deployment to be
      +For _DevOps_: programming is for your application, consider its deployment to be
       part of the documentation.
       
      -Many programmatic systems and `APIs' force you to explain how something will be
      -accomplished and the statement about `what' the outcome will be is left to an
      +Many programmatic systems and _APIs_ force you to explain how something will be
      +accomplished and the statement about _what_ the outcome will be is left to an
       implicit assumption. Such systems are called imperative systems.
       
       CFEngine is a declarative system. In a declarative system, the reverse is true.
      @@ -554,7 +553,7 @@ bundle agent name
       }
       ```
       
      -By separating `what' data like this out of the details of how they are used, it
      +By separating _what_ data like this out of the details of how they are used, it
       becomes easier to comprehend and locate, and it becomes fast to change, and the
       accuracy of the change is easily perceived. Moreover, CFEngine can track the
       impact of such a change by seeing where the data are used.
      @@ -576,7 +575,7 @@ Unix-like system do for passwords and user management.
       What you might lose when making an input matrix is the why. Is there an
       explanation that fits all these cases, or does each case need a special
       explanation? We recommend that you include as much information as possible about
      -`why'.
      +_why_.
       
       ## Packaging limits agility
       
      @@ -626,7 +625,7 @@ bundle agent example
       }
       ```
       
      -## How abstraction improves agility
      +### How abstraction improves agility
       
       Abstraction allows us to turn special cases into general patterns. This leads to
       a compression of information, as we can make defaults for the general patterns,
      @@ -662,7 +661,7 @@ need the promise, with only a small amount of work.
       Thus, simplicity is assured by having consistency of interface and low cost
       barrier to changing the meaning of the definition.
       
      -## Increasing system capacity (by scaling)
      +### Increasing system capacity (by scaling)
       
       Capacity in IT infrastructure is increased by increasing machine power. Today,
       at the limit of hardware capacity, this typically means increasing the number of
      @@ -702,7 +701,7 @@ lowest-common-denominator standardization.
       Scalability is addressed in a separate document: Scale and Scalability, so we
       shall not discuss it further here.
       
      -# Agility in your work
      +## Agility in your work
       
       * Easy versus simple
       * How does complexity affect agility?
      @@ -711,7 +710,7 @@ shall not discuss it further here.
       * What does agility cost?
       * Who is responsible for agility?
       
      -## Easy versus simple
      +### Easy versus simple
       
       Just as we separate goals from actions, and strategy from tactics, so we can
       separate what is easy from what is simple. Easy brings short-term gratification,
      @@ -733,12 +732,12 @@ Total cost of ownership is reduced if a design is simple, as there are only a
       few things to learn in total. Even if those things are hard to learn, it is a
       one-off investment and everything that follows will be easy.
       
      -Unlike some tools, with CFEngine, you do not need to program `how' to do things,
      +Unlike some tools, with CFEngine, you do not need to program _how_ to do things,
       only what you want to happen. This is always done by using the same kinds of
       declarations, based on the same model. You don't need to learn new principles
       and ideas, just more of the same.
       
      -## How does complexity affect agility?
      +### How does complexity affect agility?
       
       
       In the past[^11], it was common to manage change by making everything the same.
      @@ -748,15 +747,15 @@ therefore to agility. To put it another way, in the modern world of commerce,
       consumers rule the roost, and agility is competitive edge in a market of many
       more players than before.
       
      -Of course, it is not quite that simple. Today, we live in a culture of `ease',
      +Of course, it is not quite that simple. Today, we live in a culture of _ease_,
       and we focus on what can be done easily (low initial investment) rather than
       worrying about long term simplicity (Total Cost of Ownership).
       
      -At CFEngine, we believe that `easy' answers often suffer from the sin of
      +At CFEngine, we believe that _easy_ answers often suffer from the sin of
       over-simplification, and can lead to risky practices. After all, anyone can make
       something appear superficially easy by papering over a mess, or applying raw
       effort, but this will not necessarily scale up cheaply over time. Moreover,
      -making a risky process `too easy' can encourage haste and carelessness.
      +making a risky process _too easy_ can encourage haste and carelessness.
       
       Any problem has an intrinsic complexity, which can be measured by the smallest
       amount of information required to manage it, without loss of control.
      @@ -803,31 +802,31 @@ However, the ability to respond to complex scenarios often requires us to dabble
       with diversity. Avoiding it merely creates a lack of agility, as one is held
       back by the need to over-simplify.
       
      -## An effective understanding helps agility
      +### An effective understanding helps agility
       
       
       All configuration issues, including fitness for purpose, boil down to three
       things: why, what and how. Knowing why we do something is the most important way
       of avoiding error and risk of failure. Simplicity then comes from keeping the
      -`what' and the `how' separate, and reducing the how to a predictable, repairable
      +_what_ and the _how_ separate, and reducing the how to a predictable, repairable
       transaction. This is what CFEngine'sconvergent promisetechnology does.
       
       Knowledge is an antidote to uncertainty. Insight into patterns, brings
       simplicity to the information management, and insight into behaviour allows us
       to estimate impact of change, thus avoiding the risk associated with agility.
       
      -In configuration `what' represents transitory knowledge, while `how' is often
      +In configuration _what_ represents transitory knowledge, while _how_ is often
       more lasting and can be absorbed into the infrastructure. The consistency and
      -repairability of `how' makes it simpler to change what without risk.
      +repairability of _how_ makes it simpler to change what without risk.
       
      -## Maximizing business imperatives
      +### Maximizing business imperatives
       
       Agility allows companies and public services to compete and address the needs of
       continuous service improvement. This requires insight into IT operations from
      -business and vice versa. Recently, the `DevOps' movement in web arenas has
      +business and vice versa. Recently, the _DevOps_ movement in web arenas has
       emphasized the need for a more streamlined approach to integrating
       business-driven change and IT operations. Whatever we choose to call this, and
      -in whatever arena, `connecting the dots between business and IT' is a major
      +in whatever arena, _connecting the dots between business and IT_ is a major
       enabler for agility to business imperatives.
       
       Some business issues are inherently complex, e.g. software customization and
      @@ -849,21 +848,21 @@ insight and understanding; this, in turn, allows us to anticipate and comprehend
       challenges. CFEngine's knowledge management features help to make the
       configuration itself a part of the documentation of the system. Instead of
       relying on command line tools to interact, the user documents intentions (as
      -`promises to be kept'). These promises, and how well they have been kept, can be
      +_promises to be kept_). These promises, and how well they have been kept, can be
       examined either from the original specification or in the Mission Portal.
       
       In the industrial age, the strategy was to supply sufficient force to a small
      -problem in order to `control' it by brute force. In systems today the scale and
      +problem in order to _control_ it by brute force. In systems today the scale and
       complexity are such that no such brute force approach can seriously be expected
       to work. Thus one is reduced to a more even state of affairs: learning to work
      -with the environment `as is', with clear expectations of what is possible and
      +with the environment _as is_, with clear expectations of what is possible and
       controlling only certain parts on which crucial things depend.
       
      -## What does agility cost?
      +### What does agility cost?
       
       CFEngine is designed to have a low Total Cost of Ownership, by being
       exceptionally lightweight and conceptually simple. The investment in CFEngine is
      -a `learning curve' that some find daunting. Indeed, at CFEngine, we work on
      +a _learning curve_ that some find daunting. Indeed, at CFEngine, we work on
       reducing this initial learning curve all the time - but what really saves you in
       the end is simplicity without over-simplification.
       
      @@ -878,7 +877,7 @@ replacement the clock-time required for system updates went from 45 minutes to
       The total cost of providing for agility can be costly or it can be cheap. By
       design, CFEngine aims to make scale and agility inexpensive in the long run.
       
      -## Who is responsible for agility?
      +### Who is responsible for agility?
       
       The bottom line is: you are! Diversity and customization are basic freedoms that
       user-driven services demand in today's world, and having the agility to meet
      @@ -898,7 +897,7 @@ term, by investing in knowledge management, speed and efficiency.
       
       Footnotes
       
      -[^1]: Capacity is often loosely referred to as `bandwidth' because of its
      +[^1]: Capacity is often loosely referred to as _bandwidth_ because of its
           connection to signal propagation in communication science, but this is not
           strictly correct, as bandwidth refers to parallel channels.
       
      @@ -933,7 +932,7 @@ Footnotes
           Recovery agility plays a role in avoiding cascade failure. (ii) If the time
           to repair is long, or the repair is inaccurate, this could result if more
           widespread problems. Inaccurate change or repair often leads to attempts to
      -    `roll-back', causing further problems.
      +    _roll-back_, causing further problems.
       
       [^8]: See http://www.cfengine.com/blog/sysadmin-3.0-and-the-third-wave
       
      diff --git a/resources/additional-topics/application-management.markdown b/resources/additional-topics/application-management.markdown
      index 9c5dc3b6d..f8ab796bd 100644
      --- a/resources/additional-topics/application-management.markdown
      +++ b/resources/additional-topics/application-management.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Application Management
      +title: Application management
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is Application Management?
      +## What is application management?
       
       Application management concerns the deployment and updating of software, as well
       as customization of for actual use, in other words all the activities required
      @@ -24,7 +23,7 @@ issues.
       Using CFEngine, you can verify that the software is in a promised state and is
       properly customized for use.
       
      -# How can CFEngine help?
      +## How can CFEngine help?
       
       
       CFEngine assists with application management in a number of ways. Following the
      @@ -50,7 +49,7 @@ BDMA lifecycle, we note:
           CFEngine can monitor and report on packages and patches installed on systems
           and their versions and status.
       
      -# Package management
      +## Package management
       
       
       Application management is simple today on most operating systems due to the
      @@ -77,7 +76,7 @@ management.
       When software packages are available on local storage, CFEngine can check
       whether they are already installed, and if so, which version and architecture
       are installed. This, in turn, can be verified against the policy for the
      -software — should it indeed be installed, updated or removed?
      +software - should it indeed be installed, updated or removed?
       
       Using the CFEngine standard library, agents know how to talk to the native
       package manager to query information and get the system into the desired state.
      @@ -85,7 +84,7 @@ package manager to query information and get the system into the desired state.
       CFEngine can edit configuration files in real time to ensure that applications
       are customized to local needs at all times.
       
      -# Enterprise Software Reporting
      +## Enterprise software reporting
       
       In commercial releases of CFEngine, the state of software installation is
       reported centrally and is easily accessible through the Knowledge Map.
      @@ -94,7 +93,7 @@ Commercial editions of CFEngine also support querying Windows machines for
       installed MSI packages and thus allows for easy software deployment in
       heterogeneous Unix and Windows environments.
       
      -# Integrated software installation
      +## Integrated software installation
       
       CFEngine gives complete freedom to users, so there are many ways to design a
       system that achieves a desired software end-state. Consider the following
      @@ -111,7 +110,7 @@ standard library.
       
       ![Package Management Flow](./package-flow.png)
       
      -## Distributing software packages to client hosts
      +### Distributing software packages to client hosts
       
       To begin with, we promise that the relevant software packages will be locally
       available to the agents from software servers, i.e. we promise that a local copy
      @@ -143,7 +142,7 @@ When the agent copies a relevant software package from the software server
       defined. This class can act as a trigger to stop the application, update it, and
       start it again.
       
      -## Stopping and restarting an application for update
      +### Stopping and restarting an application for update
       
       On some operating systems, software cannot be updated while it is running.
       CFEngine can promise to enure that a program is stopped before update:
      @@ -185,7 +184,7 @@ packages:
       By promising carefully what package and version you want, using package_policy,
       package_select, and package_version, CFEngine can keep this promise by updating
       to the latest version of the package available in the directory repository
      -/software_repo. If the available versions are all `less than' than "1.0.0", an
      +/software_repo. If the available versions are all _less than_ than "1.0.0", an
       update will not take place. The package_version specification should match the
       versioning format of the software, whatever it is, e.g. you would write
       something like "1.00.00.0" if two digits were used in the two middle version
      @@ -207,7 +206,7 @@ From the promise above, we see that CFEngine will interpret app1 as the name,
       while looking at the package_name_convention in the rpm package method, we see
       that CFEngine will look for packages named as app1-X.Y.Z-i586.rpm, with X, Y, Z
       producing the largest version available in the directory repository. If an
      -available version is larger than the one installed, an update will take place —
      +available version is larger than the one installed, an update will take place -
       the update command is run.
       
       Finally, we set classes from the software update in case we want to act
      @@ -219,7 +218,7 @@ package is already installed, but installs the largest version available if it
       is not. Use package_select => "==" to install the exact version instead of the
       largest.
       
      -## Adapting to Windows
      +### Adapting to Windows
       
       To adapt our example to Windows, we change the path to the local software
       repository from/software_repotoc:\software_repo, to support the Windows path
      @@ -232,11 +231,11 @@ package_method           => msi_version("c:\software_repo"),
       
       Refer to the msi_version body in the standard library.
       
      -## Notes on Windows systems
      +### Notes on Windows systems
       
       CFEngine implements Windows packaging using the MSI subsystem, internally
       querying the Windows Management Interface for information. However, not all
      -Windows systems have the reqired information.
      +Windows systems have the required information.
       
       CFEngine relies on the name (lower-cased with spaces replaced by hyphen) and
       version fields found inside the msi packages to look for upgrades in the package
      @@ -251,7 +250,7 @@ For the formats to match, we can change the product name to 7zip and the version
       to 4.65 in the msi-package. Free tools such as InstEd can both view and change
       the product name and version (Tables->Property->ProductName and ProductVersion).
       
      -# Customizing applications
      +## Customizing applications
       
       
       By definition, we cannot explain how to customize software for all cases. For
      @@ -298,7 +297,7 @@ bundle agent my_application_customize
       You can also create file templates with customizable variables using
       theexpand_templatemethod from the standard library.
       
      -# Starting and stopping software
      +## Starting and stopping software
       
       CFEngine is promise or compliance oriented. You promise whether software will be
       running or not running at different times and locations by making processes or
      @@ -355,7 +354,7 @@ bundle agent example
       }
       ```
       
      -# Auditing software applications
      +## Auditing software applications
       
       Commercial Editions of CFEngine generate reports about installed software,
       showing package names and versions that are installed. There is a huge variety
      diff --git a/resources/additional-topics/build-deploy-manage-audit.markdown b/resources/additional-topics/build-deploy-manage-audit.markdown
      index 1d47385f0..930a76b86 100644
      --- a/resources/additional-topics/build-deploy-manage-audit.markdown
      +++ b/resources/additional-topics/build-deploy-manage-audit.markdown
      @@ -3,17 +3,16 @@ layout: default
       title: Build Deploy Manage Audit
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide, BDMA]
       ---
       
      -# What is BDMA?
      +## What is BDMA?
       
       The four mission phases are sometimes referred to as
       
       * Build
       
         A mission is based on decisions and resources that need to be assembled or
      -  `built' before they can be applied. This is the planning phase.
      +  _built_ before they can be applied. This is the planning phase.
       
         In CFEngine, what you build is a template of proposed promises for the
         machines in an organization such that, if the machines all make and keep these
      @@ -23,8 +22,8 @@ The four mission phases are sometimes referred to as
       * Deploy
       
         Deploying really means launching the policy into production. In CFEngine you
      -  simply publish your policy (in CFEngine parlance these are `promise
      -  proposals') and the machines see the new proposals and can adjust accordingly.
      +  simply publish your policy (in CFEngine parlance these are _promise proposals_)
      +  and the machines see the new proposals and can adjust accordingly.
         Each machine runs an agent that is capable of keeping the system on course and
         maintaining it over time without further assistance.
       
      @@ -45,21 +44,21 @@ The four mission phases are sometimes referred to as
       
       ![BDMA Knowledge Management Diagram](./BDMA-model.png)
       
      -# Stem cell hosts
      +## Stem cell hosts
       
       At CFEngine we talk about stem cell hosts. A stem cell host is a generic
       foundation of software that is the necessary and sufficient basis for any future
       purpose. To make a finished system from this stem cell host, you only have to
      -`differentiate' the system from this generic basis by running CFEngine.
      +_differentiate_ the system from this generic basis by running CFEngine.
       
       Differentiation of hosts involves adding or subtracting software packages,
       and/or configuring the basic system. This strategy is cost effective, as you do
      -not have to maintain more than one base-line `image' for each operating system;
      +not have to maintain more than one base-line _image_ for each operating system;
       rather, you use CFEngine to implement and maintain the morphology of the
       differences. Stem cell hosts are normally built using PXE services by booting
       and installing automatically from the network.
       
      -# Recommendations for Build
      +## Recommendations for Build
       
       There are many approaches to building complete systems. When you use CFEngine,
       you should try to progress from thinking only about putting bytes on disks, to
      @@ -91,7 +90,7 @@ optimized build that can shave off many minutes from the build time for
       machines. CFEngine can then take over where rPath leaves off, performing
       surgically precise customization.
       
      -# Recommendations for Deploy
      +## Recommendations for Deploy
       
       Deploying a policy is a potentially dangerous operation, as it will lead to
       change, with associated risk. Side-effects are common, and often result from
      @@ -131,11 +130,11 @@ CFEngine allows you to apply changes at a much finer level of granularity than
       any package based management system, thus it complements basic package
       management with its deployment and real time repair (see next section).
       
      -# Recommendations for Manage
      +## Recommendations for Manage
       
       Managing systems is an almost trivial task with CFEngine. Once a model for
       desired state has been created, you just sit back and watch. You should be ready
      -for `hands free' operation. No one should make changes to the system by hand.
      +for _hands free_ operation. No one should make changes to the system by hand.
       All changes should follow the deployment strategy above.
       
       All that remains to do is wait for email alerts from CFEngine and to browse
      @@ -153,7 +152,7 @@ computers in a single day. Learning to trust the software saves unnecessary
       communication and needless human involvement. The Nova Mission Portal makes
       notification and alerting largely unnecessary.
       
      -# Recommendations for Audit
      +## Recommendations for Audit
       
       Auditing systems is a continuous process when using CFEngine Nova. Report data
       are collected on a continuous and distributed basis. These data are then
      @@ -232,7 +231,7 @@ detail.
       
         Current variable values expanded on different hosts.
       
      -# Summary BDMA workflow
      +## Summary BDMA workflow
       
       * Define a stem cell host template.
       
      @@ -257,4 +256,4 @@ detail.
       CFEngine works well with package based management software. Users of rPath, for
       example, can achieve substantially improved efficiency in the build phase.
       CFEngine takes over where package based systems leave off, providing an
      -unprecedented level of control `hands free'.
      +unprecedented level of control _hands free_.
      diff --git a/resources/additional-topics/change-management.markdown b/resources/additional-topics/change-management.markdown
      index c8fdc6229..abfddef63 100644
      --- a/resources/additional-topics/change-management.markdown
      +++ b/resources/additional-topics/change-management.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Change Management
      +title: Change management
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is change management?
      +## What is change management?
       
       Change Management is about the planning and implementation of intended changes
       to an IT system, as well as the detection, documentation and possible repair of
      @@ -20,7 +19,7 @@ CFEngine automation, some of these approaches are considered antiquated. This
       guide explains change management in the framework of CFEngine's self-healing
       automation.
       
      -# Regulation: authorized and unauthorized change
      +## Regulation: authorized and unauthorized change
       
       It is common to speak of authorized and unauthorized change in the IT industry. Many
       organizations think in these authoritarian terms and use management techniques
      @@ -68,14 +67,14 @@ stable equilibrium. One should not believe that systems continue flawlessly
       because no intended changes are made. Change management with CFEngine should be
       about planning one stable state after another, but expecting run-time errors.
       The rate at which you move through revisions of stable policy depends on your
      -needs. The rate at which compliance is repaired should be `as soon as possible'.
      +needs. The rate at which compliance is repaired should be _as soon as possible_.
       
       To use an analogy: if policy changes are like take-off and landing, then a
       period of stable operations is like a smooth flight, on course to the correct
       destination. If unintended changes happen to change that, like the weather,
       immediate course corrections should be made to avoid loss.
       
      -# Intended and unintended change
      +## Intended and unintended change
       
       To institue a rational approach to change management, i.e. one that is suited to
       business's operational time-scales, we need to think about separating change
      @@ -90,13 +89,13 @@ services. We need to distinguish:
         maintenance).
       
       What is intended and what actually happens should not be confused. It is
      -impossible to `lock down' or fully control changes made to computer systems,
      +impossible to _lock down_ or fully control changes made to computer systems,
       without switching them off. A mandatory level of risk must be anticipated.
       
       It is by defining a desired operational state that one can avoid re-processing
       every since repair to a system.
       
      -# How fast should changes be made?
      +## How fast should changes be made?
       
       Time scales are crucially important in engineering, and deserve equal importance
       in IT management. Ask yourself: how do you know if something is changing or not?
      @@ -137,7 +136,7 @@ system at twice this rate 2R. In CFEngine, we have chosen a repair resolution of
       5 minutes for configuration sampling, because measurements show that many system
       characteristics have auto-correlations times of 10-20 minutes[^2].
       
      -# Partially centralized change
      +## Partially centralized change
       
       It is not necessary to assume a central model of authority to manage change.
       Indeed, many CFEngine users have highly devolved organizations with many
      @@ -146,8 +145,8 @@ policies, aligned with different cultures if necessary.
       
       What may be problematic is to have teams that are not aligned, so that there are
       conficting intentions. In this case, one individual might instigate a change
      -that conflicts with another. This often happens in `hit'n'run system
      -administration', where there is no concerted plan or modus operandi.
      +that conflicts with another. This often happens in _hit'n'run system administration_,
      +where there is no concerted plan or modus operandi.
       
       To keep federated teams aligned with common criteria for policy, strong
       communication is required. For this we provide access to information through the
      @@ -155,7 +154,7 @@ Mission Portal. This shows the policy itself in different regions, as well as
       reports about the compliance of systems. Users can also exchange messages about
       their intentions, through policy comments and personal logs in the system.
       
      -# The decision point
      +## The decision point
       
       By making all changes through a single point of control and verification, you
       avoid[^3] the problem of multiple intentions, because all intentions will be clear
      @@ -168,7 +167,7 @@ If you work in a federated environment, then each distinct region of policy can
       have its own policy server or hub. These will not conflict, unless a host
       subscribes to updates from more than one hub.
       
      -# Promises about change vs state
      +## Promises about change vs state
       
       CFEngine works by keeping promises, so think about how promises apply to change.
       
      @@ -204,7 +203,7 @@ CFEngine uses promises in the same way, to guide systems to their desired
       outcomes, not merely a script of relative corrections. So CFEngine works
       somewhat like a system auto-pilot.
       
      -# Promises about change
      +## Promises about change
       
       To help you think of change in terms of promises, consider the following
       promises made during change management, with CFEngine examples.
      @@ -291,7 +290,7 @@ management:
       If you have made no promise about your system state, you should not be surprised
       by anything that happens there. You cannot assume that no change will happen.
       
      -# Change management and knowledge management
      +## Change management and knowledge management
       
       
       The decision to manage change is an economic trade-off. The more promises we
      @@ -307,7 +306,7 @@ reactively.
       Knowledge Management is necessary to maintain a guidance system that makes
       course programming reliable and effective. CFEngine allows you to document all
       of your intentions as promises to be kept. CFEngine Nova additionally provides a
      -continuously updated knowledge map as part of its `auto-pilot navigation'
      +continuously updated knowledge map as part of its _auto-pilot navigation_
       facilities, based on what we promise and what it discovers about the environment
       impacting on systems. Hence, it tracks both promised state, and unintended
       changes.
      @@ -317,7 +316,7 @@ unpleasant surprises. The key to predictability in system operations is
       CFEngine's core principle of convergence. CFEngine Missions Specialists always
       think convergence.
       
      -# Non-destructive change
      +## Non-destructive change
       
       The IT industry, for the most part, has not really progressed beyond the idea of
       baselining systems. In the traditional conception of change management you start
      @@ -341,7 +340,7 @@ way, and it is our job to continuously monitor and repair this general
       dilapidation. Rather than assuming a constant state in between changes, CFEngine
       assumes a constant "ideal state" or goal to be achieved at all times.
       
      -# Change and convergence
      +## Change and convergence
       
       Change requires action, and implementation is the most dangerous part of change,
       as it leads to consquences that a difficult to predict, especially if you have
      @@ -362,14 +361,14 @@ repeated a infinite number of times[^4] without adverse consquences, because
       every action will only bring you to the desired state, no matter where you start
       from.
       
      -# The change decision process or release management
      +## The change decision process or release management
       
       The process of managing intended changes is often called release management. A
       release is a collection of authorized changes to the promises of desired state
       for a system.
       
       A release is traditionally a larger umbrella under which many smaller changes
      -are made. Changes are assembled into releases and then they are `rolled out'.
      +are made. Changes are assembled into releases and then they are _rolled out_.
       
       At CFEngine we encourage many small, incremental changes above large risky
       changes, as every change has unexpected consequences, and small changes minimize
      @@ -405,7 +404,7 @@ At each stage, we make careful, low-risk incursions on the system and see how it
       responds. Note that some side-effects could take days to emerge, so the schedule
       for change should account for the expected impact.
       
      -# Deploying policy changes
      +## Deploying policy changes
       
       The following sequence forms a checklist for deploying successful policy change:
       
      @@ -416,7 +415,7 @@ The following sequence forms a checklist for deploying successful policy change:
       
       * Make a change in the CFEngine input files.
       
      -* Run the configuration through `cf-promises --inform1 to check for problems.
      +* Run the configuration through `cf-promises --inform` to check for problems.
       
       * Commit the tested changes to promises in version control, e.g. subversion.
       
      diff --git a/resources/additional-topics/cloud-computing.markdown b/resources/additional-topics/cloud-computing.markdown
      index 0d7dee160..4090fae70 100644
      --- a/resources/additional-topics/cloud-computing.markdown
      +++ b/resources/additional-topics/cloud-computing.markdown
      @@ -1,16 +1,15 @@
       ---
       layout: default
      -title: Cloud Computing
      +title: Cloud computing
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is Cloud Computing?
      +## What is cloud computing?
       
       Cloud Computing refers to the commoditization of computing, i.e. a world in
       which computers may be borrowed on demand from a resource pool, like renting a
      -car or loaning a book from the library. The term `Cloud' comes from a model of
      +car or loaning a book from the library. The term _Cloud_ comes from a model of
       the Internet, where the precise details of how everything fits together are
       fuzzy. In a strongly networked environment, it might matter less where objects
       are physically located.
      @@ -19,10 +18,10 @@ Commoditization of computers is an important strategy for business because it
       has the potential to eliminate a lot of the investment overhead for equipment
       during times of rapid change, as well as to recycle no-longer needed resources
       and save on redundant investment. You may think of Cloud Computing as
      -`Recycle-able Computing' - a world in which you can use something for a short
      +_Recycle-able Computing_ - a world in which you can use something for a short
       time and then discard it, without fear of waste.
       
      -# Is Cloud Computing for everything and everyone?
      +## Is cloud computing for everything and everyone?
       
       Cloud Computing does for computers what the database did for information.
       Instead of having to keep reams of paper physically on site, databases allowed
      @@ -45,7 +44,7 @@ efficiently. Some people still buy books, cars and dig wells, while others loan
       books, rent cars and get water from the water authority. Different economic
       models have different applications.
       
      -# How does CFEngine enable Cloud Computing?
      +## How does CFEngine enable cloud computing?
       
       CFEngine has technology that can quickly bring machines, either real or virtual,
       from an uninitiated state to a fully working and customized state in seconds or
      @@ -54,7 +53,7 @@ into a specialized managed service on demand. CFEngine makes it extremely cheap
       to rebuild systems from scratch. This is exactly what a vibrant recycling regime
       needs to work efficiently.
       
      -# Permanent infra-structure with vibrant change
      +## Permanent infra-structure with vibrant change
       
       Not all your computers should be disposable. Certain key infrastructure items
       like DNS servers, directory servers, databases, etc are part of a permanent
      @@ -63,7 +62,7 @@ impermanence.
       
       CFEngine's lightweight repair capabilities are not only suitable for building
       machines quickly, but also for maintaining their state over time. It only pays
      -to `rent services' (either from yourself or from a third party cloud provider)
      +to _rent services_ (either from yourself or from a third party cloud provider)
       if you use the service infrequently, or your needs are constantly changing. The
       lack of permanence of cloud services can itself become an overhead if what you
       really need is constancy and security.
      @@ -73,7 +72,7 @@ investment will last you for a long time, unchanged. For that reason, cloud
       services will never solve everyone's needs all the time. It is merely one
       product of choice.
       
      -# How does Cloud relate to virtualization?
      +## How does Cloud relate to virtualization?
       
       Virtualization is the tool that makes Cloud Computing practical. Every time a
       physical machine needs to be deployed or retired, it requires the physical
      @@ -92,7 +91,7 @@ machine software is running on. CFEngine can bring stability to the hosts or the
       virtual guests, or it can keep virtual machines running without the need to
       reboot[^1].
       
      -# Isn't virtualization inefficient?
      +## Isn't virtualization inefficient?
       
       Virtualized computers run as software simulations, adding an extra layer of
       overhead. Using virtual machines is thus not as fast or processor-efficient as
      @@ -109,17 +108,17 @@ physical host container, one has a net saving of electrical power and man-power
       and often indistinguishable performance.
       
       Virtualization is a form of packaging, which enables service providers to
      -separate services more easily with a `Chinese Wall' barrier. This is useful when
      +separate services more easily with a _Chinese Wall_ barrier. This is useful when
       dealing with services belonging to different companies or different users on the
       same physical host. The packaging aspect of virtual machines is therefore a form
      -of `information management'.
      +of _information management_.
       
      -# Challenges for Cloud Computing
      +## Challenges for Cloud Computing
       
       Dealing with scale, rapid change and impermanence could quickly lead to a
       processing overhead for humans, i.e. in the management of the cloud computers.
       In order to cope, some models force an oversimplification onto the user, forcing
      -them to make do with second best (a `cheap rental').
      +them to make do with second best (a _cheap rental_).
       
       However, the requirements of computing are getting more complicated, not less.
       Even as this new economic management of resources comes into focus, companies
      @@ -148,7 +147,7 @@ can be understood both by technicians and management stakeholders.
       
       * Deployment and maintaining real or virtual machines
       
      -* Instant Managed services from `stem cell' hosts
      +* Instant Managed services from _stem cell_ hosts
       
       * Modelling the required properties of all machines and allowing non-experts
         insight into that model to see how their business goals are being handled.
      @@ -157,7 +156,7 @@ can be understood both by technicians and management stakeholders.
       
       * Bring systems from any state into compliance.
       
      -# What if I change my mind about Cloud Computing?
      +## What if I change my mind about Cloud Computing?
       
       CFEngine can be used in a public or in a private cloud, and it can be used on
       local servers, desktops and even mobile devices. CFEngine is designed to be
      @@ -167,7 +166,7 @@ you want to move a service or a server-role, it is a simple matter to do so.
       CFEngine will continue to manage the service no matter what the underlying
       resource model.
       
      -# The future - molecular computing
      +## The future - molecular computing
       
       At CFEngine, we believe that Cloud Computing is just a rehearsal for a real
       change in the way computing services are managed. In the future, the
      diff --git a/resources/additional-topics/content-driven-policy.markdown b/resources/additional-topics/content-driven-policy.markdown
      index 126c4a1fa..653b798f7 100644
      --- a/resources/additional-topics/content-driven-policy.markdown
      +++ b/resources/additional-topics/content-driven-policy.markdown
      @@ -1,13 +1,12 @@
       ---
       layout: default
      -title: Content Driven Policy
      +title: Content driven policy
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       reviewed: 2019-05-06
       ---
       
      -# What is a Content-Driven Policy?
      +## What is a content-driven policy?
       
       
       A Content-Driven Policy is a text file with lines containing semi-colon
      @@ -35,7 +34,7 @@ of masterfiles since 3.6.0. [`cdp_inputs` was removed](https://github.com/cfengi
       unified base for policy that works with both CFEngine Community and CFEngine
       Enterprise.
       
      -# Why should I use Content-Driven Policies?
      +## Why should i use content-driven policies?
       
       
       As seen in the example above, Content-Driven Policies are easy to write and
      @@ -87,7 +86,7 @@ like the following.
       * Database management
       * Application / script management
       
      -# How do Content-Driven Policies work in detail?
      +## How do content-driven policies work in detail?
       
       
       The text files in masterfiles/cdp_inputs/(e.g. 'registry_list.txt') are parsed
      @@ -98,7 +97,7 @@ policies in the text files.
       The Knowledge Map contains reports specifically designed to match the
       Content-Driven Policies.
       
      -# Can I make my own Content-Driven Policies?
      +## Can I make my own content-driven policies?
       
       
       It is possible to mimic the structure of the existing Content-Driven Policies to
      diff --git a/resources/additional-topics/devops.markdown b/resources/additional-topics/devops.markdown
      index 975d538bb..3578e1842 100644
      --- a/resources/additional-topics/devops.markdown
      +++ b/resources/additional-topics/devops.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Devops
      +title: DevOps
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is DevOps?
      +## What is DevOps?
       
       DevOps is a term coined by Patrick Debois in 2009, from an amalgamation of
       Development and Operations. It expresses a change in the way companies are
      @@ -17,7 +16,7 @@ infrastructure. It is about giving software developers more influence over the
       IT infrastructure their applications run on, and allowing change at the same
       speed as agile development teams.
       
      -# Why is DevOps happening now?
      +## Why is DevOps happening now?
       
       
       The proliferation of Free and Open Source software has put powerful software
      @@ -37,7 +36,7 @@ Traditional IT management methods can be perceived as too slow in such an
       environment. An important part of DevOps is that it naturally encompasses the
       idea of business integration - or IT for a purpose.
       
      -# Should Web and IT management be closely related?
      +## Should Web and IT management be closely related?
       
       Web frameworks have seen the rise of languages like PHP, Java, Python and Ruby,
       all of which offer frameworks for fast deployment. Languages that work well for
      @@ -62,7 +61,7 @@ load balancers in web farms.
       At CFEngine, we believe in lightweight management - made as simple as possible,
       but no simpler.
       
      -# How do we make controlled change faster?
      +## How do we make controlled change faster?
       
       
       It is important to be able to make changes quickly. Automation can implement
      @@ -70,7 +69,7 @@ change quickly if humans can get their acts together. Human IT processes and
       best practices (e.g. ITIL, COBIT, etc) tend to over bureaucratize change,
       leading to unnecessary overhead which frustrates agile companies.
       
      -To be confident and efficient (`less haste more speed'), there needs to be a
      +To be confident and efficient (_less haste more speed_), there needs to be a
       model for the system that everyone agrees on. Models compress information and
       cache understanding, meaning we have less to talk about1. Finally, models allow
       us to make predictions, so they aid understanding and help us to avoid mistake.
      @@ -82,14 +81,14 @@ requirements2. All web-based companies using credit cards will know about the
       need for PCI-DSS compliance, for instance. And US-traded companies will know
       about Sarbanes-Oxley (SOX).
       
      -# What role does CFEngine play in DevOps?
      +## What role does CFEngine play in DevOps?
       
       The challenges for IT management today are about increasing complexity (driven
       by the circuitry of online applications) and increasing scale.
       
       CFEngine is not a programming language, but a documentation language for system
       state that has the pleasant side effect of enforcing that state on a continuous
      -basis. It gets away from the idea of `build automation' to complete lifecycle
      +basis. It gets away from the idea of _build automation_ to complete lifecycle
       management. It's continuity is a natural partner for a rapid development
       environment, as mistakes can be quickly fixed on the fly with minimal impact on
       the system.
      @@ -105,7 +104,7 @@ The advantage CFEngine brings is that users can have clear expectations about
       their systems at all times. Today's programmers are more sophisticated than
       script monkeys.
       
      -# Getting used to declarative expression
      +## Getting used to declarative expression
       
       CFEngine uses a pragmatic mixture of the declarative (functional) and imperative
       to represent configurations. Programmers are taught mainly imperative
      @@ -120,7 +119,7 @@ optimized for clarity.
       The main goals of CFEngine are convergence to a desired state, repeatability and
       clear intentions.
       
      -## Expressing actions or tasks in CFEngine
      +### Expressing actions or tasks in CFEngine
       
       Most of the actionable items have builtin operational support, which is designed
       to be convergent and safely repeatable. To keep declarations clear, CFEngine
      @@ -153,7 +152,7 @@ bundle agent SomeUserDefinedName
       }
       ```
       
      -## Expressing conditionals in CFEngine
      +### Expressing conditionals in CFEngine
       
       CFEngine uses the idea of contexts (also called classes or class-contexts3) to
       address declarations to certain environments. The contexts or classes are
      @@ -233,17 +232,15 @@ decentralized manner avoiding clogging of network communications that befuddles
       many centralized approaches. This keeps CFEngine execution very fast and with a
       low overhead.
       
      -## Expressing loops in CFEngine
      +### Expressing loops in CFEngine
       
      -Lists and loops go hand in hand, and they are a very effective way of reducing
      -syntax and simplifying the expression of intent. Saying `do this to all the
      -following' is generally easier to comprehend than `do this to the first, do this
      -to the next,...' and so on, because our brains are wired to see patterns.
      +Lists and loops go hand in hand, and they are a very effective way of reducing syntax and simplifying the expression of intent.
      +Saying _do this to all the following_ is generally easier to comprehend than _do this to the first, do this to the next,..._ and so on, because our brains are wired to see patterns.
       
       Thus, loops are as useful for configuration as for programming. We only want to
      -simplify the syntax once again to hide redundant words like `foreach'. To do
      +simplify the syntax once again to hide redundant words like `foreach`. To do
       this, CFEngine makes loops implicit. If you use a scalar variable reference
      -'$(mylist)' to a list variable '@(mylist)', CFEngine assumes you want to iterate
      +`$(mylist)` to a list variable `@(mylist)`, CFEngine assumes you want to iterate
       over each case.
       
       ```cf3
      @@ -333,7 +330,7 @@ R: Hello b 4 z
       R: Hello c 4 z
       ```
       
      -## Expressing subroutines in CFEngine
      +### Expressing subroutines in CFEngine
       
       Subroutines are used for both expressing and reusing parameterizable chunks of
       code, and for naming chunks for better management of intention. In CFEngine you
      @@ -372,12 +369,12 @@ commands:
       The use of methods brings multi-dimensional patterns to convergent configuration
       management.
       
      -# Using CFEngine to integrate software components
      +##Using CFEngine to integrate software components
       
       Integration of software components may be addressed with a variety of approaches
       and techniques:
       
      -* Standard template methods from the COPBL community library (`out of the box'
      +* Standard template methods from the COPBL community library (_out of the box_
         solutions).
       
       * Customized, personalized configurations.
      diff --git a/resources/additional-topics/distributed-scheduling.markdown b/resources/additional-topics/distributed-scheduling.markdown
      index c9252c41c..e860ce549 100644
      --- a/resources/additional-topics/distributed-scheduling.markdown
      +++ b/resources/additional-topics/distributed-scheduling.markdown
      @@ -1,22 +1,21 @@
       ---
       layout: default
      -title: Distributed Scheduling
      +title: Distributed scheduling
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is distributed scheduling?
      +## What is distributed scheduling?
       
       Scheduling refers to the execution of non-interactive processes or tasks
      -(usually called `jobs') at designated times and places around a network of
      +(usually called _jobs_) at designated times and places around a network of
       computers (see the Special Topics Guide on Scheduling). Distributed Scheduling
       refers to the chaining of different jobs into a coordinated workflow that spans
       several computers. For example, you schedule a processing job
       on machine1 and machine2, and when these are finished you need to schedule a job
       on machine3. This is distributed scheduling.
       
      -# Coordinating dispatch
      +## Coordinating dispatch
       
       Dispatch is the term used for starting actually the execution of a job that has
       been scheduled. There are two ways to achieve distributed job scheduling:
      @@ -29,13 +28,13 @@ There are pros and cons to centralization. Centralization makes consistency easy
       to determine, but it creates bottlenecks in processing and allows one machine to
       see all information. Decentralization provides an automatic and natural
       load-balancing of job dispatch, and it allows machines to reveal information on
      -a `need to know' basis.
      +a _need to know_ basis.
       
       CFEngine is a naturally decentralized system, and only policy definition is
       usually centralized, but you can set up practically any architecture you like,
       in a secure fashion.
       
      -# Job scheduling and periodic maintenance
      +## Job scheduling and periodic maintenance
       
       You promise to execute tasks or keep promises at distributed places and times:
       
      @@ -56,7 +55,7 @@ This list transfers to workflow processes too. If one job needs to follow after
       another (because it depends on it for something), we can ask if this workflow is
       a standard and regular occurrence, or a one-off phenomenon.
       
      -## One-off workflows
      +### One-off workflows
       
       In CFEngine, you code a one-off workflow by specifying the space-time
       coordinates of the event that starts it. For example, if you want a job to be
      @@ -153,7 +152,7 @@ access:
       }
       ```
       
      -## Regular workflows
      +### Regular workflows
       
       To make a job happen at a specific time, we used a very specific time classifier
       'Day24.January.Year2012.Hr16.Min45_50'. If we now want to make this workflow
      @@ -209,7 +208,7 @@ commands:
       ```
       
       
      -# Fancy distributed encapsulation
      +## Fancy distributed encapsulation
       
       We could try to be fancy about distributed scheduling, packaging it into a
       reusable structure. This may or may not be a good idea, depending on your
      @@ -322,7 +321,7 @@ access:
       }
       ```
       
      -# More links in the chain
      +## More links in the chain
       
       In the examples above, we only had two hosts cooperating about jobs. In general,
       it is not a good idea to link together many different hosts unless there is a
      @@ -339,7 +338,7 @@ number of jobs to drive a single follow-up.
       
       ![Scheduling Patterns](./scheduleing-patterns.png)
       
      -## Aggregation of multiple jobs
      +### Aggregation of multiple jobs
       
       When aggregating jobs, we must combine their exit status using AND or OR. The
       most common case it that we require all the prerequisites in place in order to
      @@ -396,7 +395,7 @@ bundle agent example
       }
       ```
       
      -## Triggering multiple follow-ups
      +### Triggering multiple follow-ups
       
       The converse scenario is to trigger a number of jobs from a single
       pre-requisite. This is simply a case of listing the jobs under the trigger
      @@ -432,7 +431,7 @@ commands:
               classes => state_repaired("did_my_job");
       ```
       
      -# Self-healing workflows
      +## Self-healing workflows
       
       To apply CFEngine's self-healing concepts to workflow scheduling, we can imagine
       the concept of a convergent workflow, i.e. one that, if we repeat everything a
      @@ -444,14 +443,14 @@ think in terms of repeatable sustainable outcomes and fault-tolerance.
       
       Beware however, one-off jobs cannot be made convergent, because they only have a single chance to succeed. It is a question of business process design whether you design workflows to be sustainable and repeatable, or whether you trust the outcome of a single shot process. Using the persistent classes in CFEngine together with the if-elapsed locks to send signals between hosts, it is simple and automatic to make convergent self-healing workflows.
       
      -# Long workflow chains
      +## Long workflow chains
       
       Long workflow chains are those which involve more than one trigger. These can be
       created by repeating the pattern above several times. Note however, that each
       link in the chain introduces a new level of uncertainty and potential failure.
       In general, we would not recommend creating workflows with long chains.
       
      -# Summary of Distributed Scheduling
      +## Summary of distributed scheduling
       
       Distributed scheduling is about tying together jobs to create a workflow across
       multiple machines. It introduces a level of fragility into system automation.
      diff --git a/resources/additional-topics/file-content.markdown b/resources/additional-topics/file-content.markdown
      index f1d0928a0..fce9e0b37 100644
      --- a/resources/additional-topics/file-content.markdown
      +++ b/resources/additional-topics/file-content.markdown
      @@ -1,18 +1,17 @@
       ---
       layout: default
      -title: File Content
      +title: File content
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# From boiler-plates to convergent file editing
      +## From boiler-plates to convergent file editing
       
       Many configuration management systems allow you to determine configuration file
       content to some extent, usually by over-writing files with boiler-plate
       (template) files. This approach works for some cases, but it is a blunt and
       inflexible instrument, which forces you to take over the ownership of the file
      -`all or nothing' and determine its entire content yourself. This is more than is
      +_all or nothing_ and determine its entire content yourself. This is more than is
       necessary or desirable in general.
       
       Other approaches to file editing us search and replace, e.g. with the
      @@ -31,7 +30,7 @@ being predictable. There are three ways to approach this problem. You should
       choose the simplest approach that solves your problem and try not to be
       prejudiced by what you have done before.
       
      -# Why is file editing difficult?
      +## Why is file editing difficult?
       
       File content is not made up of simple data objects like permission flags or
       process tables: files contain compound, ordered structures (known as grammars)
      @@ -39,7 +38,7 @@ and they cannot always be determined from a single source of information. To
       determine the outcome of a file we have to adopt either a fully deterministic
       approach, or live with a partial approximation.
       
      -Some approaches to file editing try to `know' the intended format of a file, by
      +Some approaches to file editing try to _know_ the intended format of a file, by
       hardcoding it. If the file then fails to follow this format, the algorithms
       might break. CFEngine gives you generic tools to be able to handle files in any
       line-based format, without the need to hard-code specialist knowledge about file
      @@ -48,7 +47,7 @@ formats.
       Remember that all changes are adapted to your local context and implemented at
       the final destination by cf-agent.
       
      -# What does file editing involve?
      +## What does file editing involve?
       
       
       There are several ways to approach desired state management of file contents:
      @@ -77,7 +76,7 @@ of the file you are starting from. Approach 3 is generally required when
       adapting configuration files provided by a third party, since the basic content
       is determined by them.
       
      -# Three approaches to managing files
      +## Three approaches to managing files
       
       * Copying a finished file template into place
       
      @@ -89,7 +88,7 @@ is determined by them.
       
       * Making delta changes to someone else's file
       
      -## Copying a finished file template into place
      +### Copying a finished file template into place
       
       Use this approach if a simple substution of data will solve the problem in all
       contexts.
      @@ -111,7 +110,7 @@ files:
       }
       ```
       
      -## Contextual adaptation of a file template
      +### Contextual adaptation of a file template
       
       There are several approaches here:
       
      @@ -232,7 +231,7 @@ nameserver 2
       nameserver 3
       ```
       
      -## Example file template
      +### Example file template
       
       ```
       [%CFEngine any:: %]
      @@ -266,7 +265,7 @@ nameserver 3
       [%CFEngine END %]
       ```
       
      -## Combining copy with template expansion
      +### Combining copy with template expansion
       
       What about getting your template to the end-host? To convergently copy a file
       from a source and then edit it, use the following construction with a staging
      @@ -297,7 +296,7 @@ replace_patterns:
       }
       ```
       
      -## Making delta changes to someone else's file
      +### Making delta changes to someone else's file
       
       Edit a file with multiple promises about its state, when you do not want to
       determine the entire content of the file, or if it is unsafe to make unilateral
      @@ -349,7 +348,7 @@ delete_lines:
       }
       ```
       
      -# Constructing files from promises
      +## Constructing files from promises
       
       
       Making finished templates for files and filling in the blanks using variables is
      @@ -362,7 +361,7 @@ files that are read in.
       If you are using CFEngine 3.3 or later, you have the option of using
       edit_template and its embedded language constructs to keep decisions and loops
       inside templates. Let's set aside that for a while and look at the alternatives,
      -placing the data entirely within bundles of `edit'-promises.
      +placing the data entirely within bundles of `edit`-promises.
       
       There is language support for this kind of editing in the standard library, and
       you can store data and template components within a CFEngine configuration
      @@ -416,7 +415,7 @@ host$ more /tmp/my_result
          e.g Mary had a little lamb
       ```
       
      -## Adding a line here and there
      +### Adding a line here and there
       
       A simple file like this could also be defined in-line, without a separate
       template file:
      @@ -455,7 +454,7 @@ files:
       }
       ```
       
      -## Lists inline
      +### Lists inline
       
       
       Here is a more complicated example, that includes list expansion. List expansion
      @@ -693,7 +692,7 @@ insert_lines:
       }
       ```
       
      -# Editing bundles
      +## Editing bundles
       
       Unlike other aspects of configuration, promising the content of a single file
       object involves possibly many promises about the atoms within the file. Thus we
      @@ -732,7 +731,7 @@ insert_lines:
       
       * Expressing expand_template as promises
       
      -## Standard library methods for simple editing
      +### Standard library methods for simple editing
       
       You may choose to write your own editing bundles for specific purposes; you can
       also use ready-made templates from the standard library for a lot of purposes.
      @@ -789,7 +788,7 @@ Some other examples of the standard editing methods are:
       
       You find these in the documentation for the COPBL.
       
      -## Expressing expand_template as promises
      +### Expressing expand_template as promises
       
       As on CFEngine 3.3.0, CFEngine has a new template mechanism to make it easier to
       encode complex file templates. These templates map simply to edit_line bundles
      @@ -820,7 +819,7 @@ bundle agent example
       }
       ```
       
      -# Choosing an approach to file editing
      +## Choosing an approach to file editing
       
       There are two decisions to make when choosing how to manage file content:
       
      @@ -835,7 +834,7 @@ How can the desired content be constructed from the necessary source(s)?
       Use the simplest approach that requires the smallest number of promises to solve
       the problem.
       
      -# Pitfalls to watch out for in file editing
      +## Pitfalls to watch out for in file editing
       
       File editing is different from most other kinds of configuration promise because
       it is fundamentally an order dependent configuration process. Files contain
      diff --git a/resources/additional-topics/glossary.markdown b/resources/additional-topics/glossary.markdown
      deleted file mode 100644
      index 61526b6cc..000000000
      --- a/resources/additional-topics/glossary.markdown
      +++ /dev/null
      @@ -1,262 +0,0 @@
      ----
      -layout: default
      -title: Glossary
      -published: true
      -sorting: 80
      -tags: [overviews, special topics, guide]
      ----
      -
      -* Agent
      -
      -  A piece of software that runs independently and automatically to carry out a
      -  task (think software robot). Inn CFEngine, the agent is called cf-agent and is
      -  responsible for making changes to computers.
      -
      -* Amber host
      -
      -  A host that has repaired more than 20% of its scheduled promises in the past 5
      -  minutes. (See yellow host.)
      -
      -* Body
      -
      -  A promise body is the description of exactly what is promised (as opposed to
      -  what/who is making the promise). The term `body' is used in the CFEngine
      -  syntax to mean a small template that can be used to contribute as part of a
      -  larger promise body.
      -
      -* Bundle
      -
      -  In CFEngine, a bundle refers to a collection of promises that has a name.
      -
      -* CDP
      -
      -  Content Driven Policy. A way of simplifying the way users provide information
      -  to CFEngine about policy by hiding the overhead of policy coding. A CDP is a
      -  set of promises that is designed to solve a particular task in a standard way.
      -  Users provide only a little data in the form of a simple spreadsheet of data
      -  in a table.
      -
      -* CFEngine
      -
      -  The name of the CFEngine Company, as well as the name of the Software.
      -  CFEngine comes from a contraction of `ConFiguration Engine'.
      -
      -* CFEngine 3.x
      -
      -  Major version 3 of the CFEngine software, started in 2008 and going up to the
      -  present day. This comes in several editions, both Open Source and Commercial.
      -
      -* CFEngine Community Edition
      -
      -  Free and Open Source edition of the CFEngine software, published under the
      -  GPL3 license, and optionally under the COSL license.
      -
      -* CFEngine Community Open Promise-Body Library
      -
      -  A collection of standard definitions that is open to the user community for
      -  comment and standardization.
      -
      -* CFEngine Constellation
      -
      -  An enterprise edition of CFEngine, that is designed to scale to huge systems
      -  by using a federated design. Constellation allows better handling of groups
      -  (i.e. constellations of objects) in a network.
      -
      -* CFEngine Enterprise Editions
      -
      -  Refers to commercial (paid) editions of the CFEngine software, published under
      -  the COSL license.
      -
      -* CFEngine Nova
      -
      -  The lowest level enterprise edition of CFEngine, that automatically creates a
      -  simple `star network' mangement model for hosts in an environment.
      -
      -* ChangeLog
      -
      -    A file used to describe the changes made since the last version of the
      -    software.
      -
      -* CMDB
      -
      -  A Configuration Management Database. A term coined as part of the IT
      -  Infrastructure Library (ITIL) as an outgrowth of an inventory database.
      -
      -* CMS
      -
      -  Content Management System. A kind of editor for maintaining something (often
      -  web pages).
      -
      -* Code branch
      -
      -  The development of software is a branching process. At certain times, the
      -  software code splits into different versions following different paths. Each
      -  path needs to be maintained separately for a while. This often happens when a
      -  release is made, because one wants to freeze the development of a public
      -  release (allowing nevertheless for some minor bugfixes), while continuing to
      -  add features to a branch leading to future versions.
      -
      -* COPBL
      -
      -  CFEngine Community Open Promise-Body Library (abbrev: CFEngine standard
      -  library). A collection of standard definitions.
      -
      -* COSL license
      -
      -  The Commercial Open Source License used for the CFEngine
      -
      -* CSS
      -
      -  Cascading Style Sheets. Part of Web technology used to describe page design.
      -
      -* Diff
      -
      -  A `diff' is a report (originally that generated by the UNIX diff command) that
      -  details the differences between two files. The term is often used as slang
      -  meaning a file comparison.
      -
      -* GPL3
      -
      -  The GNU Public License, version 3.
      -
      -* Green Host
      -
      -  A host for which more than 80% of all promises are kept.
      -
      -* GUI
      -
      -  Graphical User Interface.
      -
      -* Host
      -
      -  UNIX terminology for a computer the runs `guest programs'. In practice, `host'
      -  is a synonym for `computer'.
      -
      -* Hub
      -
      -  A software component in CFE Nova and CFE Constellation that works as a single
      -  point of management in a local `star-network'. The term hub is sometimes used
      -  to mean policy distribution server, but more commonly a running cf-hub process
      -  that does report collection from all CFEngine managed hosts. The term hub
      -  means the centre of a wheel, from which multiple spokes emerge.
      -
      -* Knowledge Map
      -
      -  A master index of all the information known about a CFEngine managed
      -  environment, represented as a set of web pages with an interactive interface
      -  based on a `semantic web'. The CFEngine Mission Portal provides a web-based
      -  interface for browsing this knowledge map index.
      -
      -* Mission
      -
      -  The mission refers to the raison d'\hat etre of an organization. CFEngine's
      -  task is to support this mission by keeping a set of promises for its IT
      -  infrastructure.
      -
      -* Mission Portal
      -
      -  The name given to the user interface used in commercial CFEngine editions,
      -  where all reports and progress summaries are kept.
      -
      -* Modular license
      -
      -  A license granting partial functionality to an Enterprise Edition of CFEngine.
      -
      -* LDAP
      -
      -  The Lightweight Directory Access Protocol. A kind of `phone book' service
      -  providing information about persons and computers in an organization.
      -
      -* Libraries
      -
      -  A library generally refers to collection of standardized CFEngine code that
      -  can be reused in different scenarios and environments. This might be bundles
      -  of promises, or reusable body-parts.
      -
      -* Packages
      -
      -  Software binaries or executable files. The CFEngine company compiles and tests
      -  software into packages suitable for different platforms.
      -
      -* Platforms
      -
      -  This usually refers to an operating system type, e.g. Linux (in its many
      -  flavours), or Windows, etc. Platforms are described using short identifiers,
      -  e.g. RH5, REL5, SuSE 11, SLES, etc.
      -
      -* Knowledge Map
      -
      -  Content portal containing datacentre information, privately managed knowledge
      -  resources and CFEngine documentation.
      -
      -* PCI compliance
      -
      -  Payment Card Industry Data Security Standard (PCI DSS) is a set of
      -  requirements designed to ensure that ALL companies that process, store or
      -  transmit credit card information maintain a secure environment.
      -
      -* Promise
      -
      -  The CFEngine software manages every intended system outcome as `promises' to
      -  be kept. A CFEngine Promise corresponds roughly to a rule in other software
      -  products, but importantly promises are always things that can be kept and
      -  repaired continuously, on a real time basis, not just once at install-time.
      -
      -* Policy
      -
      -  A policy is a set of intentions about the system, coded as a list of promises.
      -  A policy is not a standard, but the result of specific organizational
      -  management decisions.
      -
      -* Semantic web
      -
      -  A form of web content in which hyperlinks always explain the meaning of the
      -  information they point to, in relation to the subject of interest. Semantic
      -  web technologies include RDF, Topic Maps etc.
      -
      -* Server
      -
      -  A term used in many different ways, riddled with confusion. A server is
      -  strictly a piece of software that runs on some computer in order to perform a
      -  service, e.g. a web server is a program that makes a computer part of the
      -  World Wide Web. For historical reasons, certain computers are referred to as
      -  servers, especially when kept in datacentres because such computers often run
      -  services. In CFEngine, cf-serverd is a software component that serves files
      -  from one computer to another. All computers are recommended to run cf-serverd,
      -  making all computers CFEngine servers, whether they are laptops, phones or
      -  datacentre computers.
      -
      -* Service Catalogue
      -
      -  A kind of directory of `services' provided in an environment. The concept of a
      -  service could be anything from a human help desk to a machine controlled email
      -  subsystem. In the CFEngine Mission Portal, the service catalogue (for
      -  maintenance) treats promise-bundles of promises as low-level maintenance
      -  services, and relates these to high level business goals.
      -
      -* SOX Compliance
      -
      -  Sarbanes-Oxley Act compliance. An audited accolade for financial data security
      -  required by all companies on the New York stock exchange.
      -
      -* Standard library
      -
      -  The CFEngine Standard library is a collection of standardized definitions (see
      -  COPBL).
      -
      -* Template
      -
      -  A template is an incomplete piece of CFEngine code, with blanks to fill in. It
      -  is often a policy fragment that can be re-used in different scenarios. This is
      -  often used interchangeably with the term `library'.
      -
      -* UI
      -
      -  User interface.
      -
      -* Yellow host.
      -
      -  See amber host.
      -
      -This work is licensed under a Creative Commons Attribution-ShareAlike 3.0
      -Unported License (http://creativecommons.org/licenses/by-sa/3.0/).
      diff --git a/resources/additional-topics/hierarchies.markdown b/resources/additional-topics/hierarchies.markdown
      index 8ded2c662..d82350888 100644
      --- a/resources/additional-topics/hierarchies.markdown
      +++ b/resources/additional-topics/hierarchies.markdown
      @@ -3,12 +3,11 @@ layout: default
       title: Hierarchies
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
       Authority, Structure and Inheritance
       
      -# What is a hierarchy?
      +## What is a hierarchy?
       
       A hierarchy is an organizational structure with tree-like branches. In a
       hierarchy, parts of the system belong to other parts, like collections of boxes
      @@ -19,12 +18,12 @@ Acyclic Graphs (DAG) in mathematics (see figure below (a) and (b)).
       ![Network Organizational Structures](./network-organizational-structures.png)
       
       Hierarchies are often associated withauthority, as we use hierarchies to
      -organize human `chains of command'. In this case, a hierarchy typically has
      +organize human 'chains of command'. In this case, a hierarchy typically has
       multiple levels, as in (b). You might interpret this diagram as showing a single
       point of top level management, then satellite areas of middle management each
       with their own clusters of slaves (leaf nodes). When drawing hierarchies, the
       root of the tree is placed at the top or centre of the picture and is considered
      -to beauthoritative, i.e. more important than the `leaves'. Each leaf node is
      +to beauthoritative, i.e. more important than the 'leaves'. Each leaf node is
       then subject to the control of the root in a top down manner.
       
       The opposite of a hierarchy is a mesh or web (figure (c)), which has no special
      @@ -34,10 +33,10 @@ on demand to other nodes, without any particular ranking. If you move in a mesh,
       you cannot easily measure how far you are away from a given point, as their
       might be more than one way of getting there.
       
      -Mesh architectures are often robust to failure as there can be multiple `peer to
      -peer' routes for passing messages or information.
      +Mesh architectures are often robust to failure as there can be multiple
      +_peer to peer_ routes for passing messages or information.
       
      -Top-down is is a cultural prejudice or `norm', as most human societies work in
      +Top-down is is a cultural prejudice or _norm_, as most human societies work in
       this way. However it is not a necessity. A network service is bottom-up - there
       it is the leaves which drive requests that end at a single central server.
       Hierarchies are special cases of networks, and (as all special cases) they are
      @@ -47,7 +46,7 @@ that point will disconnect the network.
       
       ![Single points of failure](./single-points-of-failure.png)
       
      -# How hierarchy compares to sets
      +## How hierarchy compares to sets
       
       Some languages (like Object Oriented languages) are designed to enforce
       hierarchies. CFEngine is not one of these. In CFEngine you can build a hierarchy
      @@ -62,11 +61,11 @@ bundle agent example
       {
         classes:
       
      -   # Conceptual hierarchy
      +    # Conceptual hierarchy
       
      -   "top"      or => { "middle_1", "middle_2", "middle_3" };
      -   "middle_1" or => { "slave_1",  "slave_2",  "slave_3"  };
      -   "middle_2" or => { "slave_4",  "slave_5",  "slave_6"  };
      +    "top"      or => { "middle_1", "middle_2", "middle_3" };
      +    "middle_1" or => { "slave_1",  "slave_2",  "slave_3"  };
      +    "middle_2" or => { "slave_4",  "slave_5",  "slave_6"  };
       }
       ```
       
      @@ -81,9 +80,8 @@ finance, engineering and legal departments in three countries.
       bundle agent example
       {
         classes:
      -
      -     "headquarters"  or => { "usa",      "uk",           "norway" };
      -     "department"    or => { "finance",  "engineering",  "legal"  };
      +    "headquarters"  or => { "usa",     "uk",          "norway" };
      +    "department"    or => { "finance", "engineering", "legal"  };
       }
       ```
       
      @@ -119,7 +117,7 @@ prevents that. The key is to notice that the `.` (dot) operator is really an
       intersection of sets (AND)1, and that this is a much more flexible notion than
       hierarchy.
       
      -# Classes are sets
      +## Classes are sets
       
           `Sets, sets, sets ... all you ever think about it sets!`
       
      @@ -166,11 +164,12 @@ set union (OR or '|') and intersection (AND or '.'):
       bundle agent example
       {
         classes:
      -
      -    "headquarters"  or => { "usa",      "uk",           "norway" };
      -    "department"    or => { "finance",  "engineering",  "legal"  };
      -
      - "english_speaking" expression => "(usa|uk).!legal";
      +    "headquarters"
      +      or => { "usa", "uk", "norway" };
      +    "department"
      +      or => { "finance", "engineering", "legal"};
      +    "english_speaking"
      +      expression => "(usa|uk).!legal";
       
       }
       ```
      @@ -178,7 +177,7 @@ bundle agent example
       Thus the English speakers are those entities belonging to the USA `AND` the UK,
       excepting presumably the legal department.
       
      -# For and against hierarchies
      +## For and against hierarchies
       
       Hierarchies are good at bringing consistency. They are bad at scaling. They
       bring consistency because the root node acts as a single point of authority,
      @@ -200,7 +199,7 @@ CFEngine does not encourage it.
       This document tries to show how to use hierarchy sensibly and usefully to
       simplify rather than to enforce authority.
       
      -# Inheritance and its forms
      +## Inheritance and its forms
       
       Perhaps the most popular application of hierarchy is to use the property of
       having a single-point of definition to avoid maintaining the same information in
      @@ -232,7 +231,7 @@ the users or consumers of the information are so-called derived classes.
       We can use the notion of inheritance at different levels within CFEngine. These
       are a matter of using the global scope with bundle names.
       
      -## Inheritance of classes/sets
      +### Inheritance of classes/sets
       
       We can aggregate smaller classes into larger ones (yielding multiple inheritance
       of class attributes):
      @@ -241,40 +240,39 @@ of class attributes):
       bundle agent example
       {
         classes:
      -
      -    "group_name" or => {
      -                       "base_class_1",
      -                       "base_class_2",
      -                       "base_class_3"
      -                       };
      +    "group_name"
      +      or => {
      +        "base_class_1",
      +        "base_class_2",
      +        "base_class_3",
      +      };
       }
       ```
       
       Note that CFEngine naturally forms a bottom-up hierarchy, never a top-down
       hierarchy.
       
      -## Inheritance of class definitions
      +### Inheritance of class definitions
       
       CFEngine divides its promises into bundles that have private classes and
       variables. Bundles called `common bundles` define global classes, so they are
       automatically inherited by all other bundles.
       
      -## Inheritance of variable definitions
      +### Inheritance of variable definitions
       
       Variables in CFEngine are globally accessible, but you must say what bundle you
      -are talking about by writing '$(bundle.scalar)' or '@(bundle.list)'. If you omit
      +are talking about by writing `$(bundle.scalar)` or `@(bundle.list)`. If you omit
       the `bundle`, it is assumed that the variable is in the current bundle.
       
       ```cf3
       bundle agent child_bundle(parameter)
       {
         vars:
      -
      -    "extend_list" slist => { "extension", @(foreign.list) },
      -                 policy => "ifdefined";
      +    "extend_list"
      +      slist => { "extension", @(foreign.list) },
      +      policy => "ifdefined";
       
         reports:
      -
           "Inherit parameter value $(parameter)";
           "Inherit foreign scalar value $(foreign.scalar)";
       
      @@ -285,7 +283,7 @@ The policy ifdefined means that CFEngine will ignore the foreign list if it does
       not exist. This means you can include a number of lists from other bundles to
       extend the behviour of your own, if they are provided.
       
      -## Inheritance of bundles
      +### Inheritance of bundles
       
       Bundles cannot really be merged like sets, but since they make promises you can
       use them.
      @@ -294,8 +292,8 @@ use them.
       bundle agent child_bundle
       {
         methods:
      -
      -    "extend_method" use => base_bundle(parameter1,parameter2);
      +    "extend_method"
      +      use => base_bundle(parameter1,parameter2);
       }
       ```
       
      @@ -323,7 +321,7 @@ of authority, by promising to use the inheritance, you have subordinated your
       input to the source - or voluntarily given up the right to say no to whatever
       you have subscribed to. You have implicity trusted them.
       
      -# Expressing `is a` or `has a`
      +## Expressing `is a` or `has a`
       
       Let us re-emphasize for the record that CFEngine is not intended to be an object
       oriented system. At CFEngine we do not believe that Object Orientation is a good
      @@ -348,18 +346,16 @@ the set of servers:
       bundle agent example
       {
         classes:
      -
      -    "servers"  or => { "host1", "host2" };
      +    "servers"
      +      or => { "host1", "host2" };
       
         processes:
      -
           servers::  # the next rules `extend` or add to the class servers
      -
             "..."
       }
       ```
       
      -# How to organize your organization
      +## How to organize your organization
       
       Faced with the choice of how to classify systems, where does one begin? This is
       the dilemma that programmers face when designing new software, and if they make
      @@ -375,21 +371,16 @@ In other words, what is that basic paradigm that you use to partition your
       system operations? Some alternatives include:
       
       * Geographically (by site or country)
      -
       * By business department (sales, accounting, research)
      -
       * By security zone (private, DMZ, public, etc)
      -
       * By operating system (solaris, linux, darwin)
      -
       * By customer or client (e.g. for managed services)
      -
       * By task, service or role in the network (webservers, dns, workstations)
       
       However, you choose to begin, you can further subdivide these major categories
       by simply ANDing with other categories.
       
      -# Applications of hierarchy
      +## Applications of hierarchy
       
       When a small organization uses CFEngine, machines are often configured by "what
       they do" or "what they have" (e.g., they "are a webserver" or they "have
      @@ -403,40 +394,32 @@ For example:
       bundle agent maintain_servers
       {
         classes:
      -    "has_dhcpd"	or	=> { classmatch("ipv4_10_\d+_\d+_1") };
      -  	"has_httpd"	or	=> { "www_example_com" };
      -  	"has_sshd"	or	=> { "any" };
      +    "has_dhcpd"
      +      or => { classmatch("ipv4_10_\d+_\d+_1") };
      +    "has_httpd"
      +      or => { "www_example_com" };
      +    "has_sshd"
      +      or => { "any" };
       
         processes:
      -
           has_dhcpd::
      -
      -      "dhcpd" restart_class => "start_dhcpd";
      -
      +      "dhcpd"
      +        restart_class => "start_dhcpd";
           has_httpd::
      -
      -  	  "httpd" restart_class => "start_httpd";
      -
      +      "httpd"
      +        restart_class => "start_httpd";
           has_sshd::
      -
      -       "sshd" restart_class => "start_sshd";
      +      "sshd"
      +        restart_class => "start_sshd";
       
         commands:
      -
           freebsd.start_dhcpd::
      -
             "/usr/local/etc/rc.d/isc-dhcpd.sh start";
      -
           start_httpd::
      -
             "/usr/local/sbin/apachectl start";
      -
           freebsd.start_sshd::
      -
             "/etc/rc.d/sshd start";
      -
           linux.start_sshd::
      -
             "/etc/init.d/ssh start";
       }
       ```
      @@ -458,22 +441,22 @@ bundle agent example
         files:
       
           internal.has_httpd.nyc::
      -	# Files maintained for internal webserver in New York
      +      # Files maintained for internal webserver in New York
       
           external.has_httpd.nyc::
      -	# Files maintained for external webserver in New York
      +      # Files maintained for external webserver in New York
       
           internal.has_httpd.london::
      -	# Files maintained for internal webserver in London
      +      # Files maintained for internal webserver in London
       
           external.has_httpd.london::
      -	# Files maintained for external webserver in London
      +      # Files maintained for external webserver in London
       
           internal.has_httpd.tokyo::
      -	# Files maintained for internal webserver in Tokyo
      +      # Files maintained for internal webserver in Tokyo
       
           external.has_httpd.tokyo::
      -	# Files maintained for external webserver in Tokyo
      +      # Files maintained for external webserver in Tokyo
       }
       ```
       
      @@ -486,26 +469,14 @@ using CFEngine to centrally administer a large network of computers, but there
       are other ways of doing this that make maintenance easier and the logic more
       apparent.
       
      -1) Copying files to local machines
      -2) Symlinks
      -3) Local changes $(site_local)
      -4) Machine naming -> classes
      -5) Using dist classes to select from a set of machines, not just query them in order; also splayclass
      -6) Versioning, RPM/SVN for distro, vs CFEngine
      -7) updating with cf-agent -DUpdateNow
      -
      -Table of Contents
      -
      -    Hierarchies
      -        What is a hierarchy?
      -        How hierarchy compares to sets
      -        Classes are sets
      -        For and against hierarchies
      -        Inheritance and its forms
      -        Expressing `is a` or `has a`
      -        How to organize your organization
      -        Applications of hierarchy
      -
      -Footnotes
      +1. Copying files to local machines
      +2. Symlinks
      +3. Local changes $(site_local)
      +4. Machine naming -> classes
      +5. Using dist classes to select from a set of machines, not just query them in order; also splayclass
      +6. Versioning, RPM/SVN for distro, vs CFEngine
      +7. updating with cf-agent -DUpdateNow
      +
      +## Footnotes
       
       [1] It is a commutative operator, which is why it makes sense to write both usa.finance and finance.usa.
      diff --git a/resources/additional-topics/iteration.markdown b/resources/additional-topics/iteration.markdown
      index 48e0eb7c2..6f75739a6 100644
      --- a/resources/additional-topics/iteration.markdown
      +++ b/resources/additional-topics/iteration.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: Iteration (Loops)
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is iteration?
      +## What is iteration?
       
       Iteration is about repeating operations in a list. In CFEngine, iteration is
       used to make a number of related promises, that fall into a pattern based on
      @@ -25,7 +24,7 @@ scalar reference `$(list)`, then CFEngine understands this to mean, take each
       scalar item in the list and repeat the current promise, replacing the instance
       with elements of the list in turn.
       
      -# Iterated promises
      +## Iterated promises
       
       Consider the following set of promises to report on the values of four separate
       monitor values:
      @@ -33,12 +32,12 @@ monitor values:
       ```cf3
       bundle agent no_iteration
       {
      -reports:
      -  cfengine_3::
      -    "mon.value_rootprocs is $(mon.value_rootprocs)";
      -    "mon.value_otherprocs is $(mon.value_otherprocs)";
      -    "mon.value_diskfree is $(mon.value_diskfree)";
      -    "mon.value_loadavg is $(mon.value_loadavg)";
      +  reports:
      +    cfengine_3::
      +      "mon.value_rootprocs is $(mon.value_rootprocs)";
      +      "mon.value_otherprocs is $(mon.value_otherprocs)";
      +      "mon.value_diskfree is $(mon.value_diskfree)";
      +      "mon.value_loadavg is $(mon.value_loadavg)";
       }
       ```
       
      @@ -56,19 +55,18 @@ reports:
       ```cf3
       bundle agent iteration1
       {
      -vars:
      -    "monvars" slist => {
      -                       "rootprocs",
      -                       "otherprocs",
      -                       "diskfree",
      -                       "loadavg"
      -                       };
      -
      -reports:
      -
      -  cfengine_3::
      -
      -    "mon.value_$(monvars) is $(mon.value_$(monvars))";
      +  vars:
      +    "monvars"
      +      slist => {
      +       "rootprocs",
      +       "otherprocs",
      +       "diskfree",
      +       "loadavg"
      +     };
      +
      +  reports:
      +    cfengine_3::
      +      "mon.value_$(monvars) is $(mon.value_$(monvars))";
       }
       ```
       
      @@ -88,7 +86,7 @@ the semantics of the reports from the list of monitoring variables.
       Admittedly, this is a simple example, but if you understand this one, we can
       continue with more compelling examples.
       
      -# Iterating across multiple lists
      +## Iterating across multiple lists
       
       
       Although iteration is a powerful concept in and of itself, CFEngine can iterate
      @@ -101,19 +99,20 @@ The answer is simply to do another iteration:
       ```cf3
       bundle agent iteration2
       {
      -vars:
      -    "stats"   slist => { "value", "av", "dev" };
      -
      -    "monvars" slist => {
      -                       "rootprocs",
      -                       "otherprocs",
      -                       "diskfree",
      -                       "loadavg"
      -                       };
      -reports:
      -
      -  cfengine_3::
      -    "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
      +  vars:
      +    "stats"
      +      slist => { "value", "av", "dev" };
      +    "monvars"
      +      slist => {
      +        "rootprocs",
      +        "otherprocs",
      +        "diskfree",
      +        "loadavg"
      +      };
      +
      +  reports:
      +    cfengine_3::
      +      "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
       }
       ```
       
      @@ -124,7 +123,7 @@ report on `value_rootprocs`, `av_rootprocs`, and `dev_rootprocs`, followed next
       leftward lists are iterated over completely before going to the next value in
       the rightward lists.
       
      -# Iterating over nested lists
      +## Iterating over nested lists
       
       Recall that CFEngine iterates over complete promise units, not small parts of a
       promise. Let's look at an example that could show a common misunderstanding.
      @@ -137,22 +136,22 @@ might not do what you expect.
       ```cf3
       bundle agent iteration3a
       {
      -vars:
      +  vars:
           "stats" slist => { "value", "av", "dev" };
           "inout" slist => { "in", "out" };
      -
           "monvars" slist => {
      -		"rootprocs",	"otherprocs",
      -		"diskfree",
      -		"loadavg",
      -		"smtp_$(inout)",  #
      -		"www_$(inout)",   # look here
      -		"wwws_$(inout)"   #
      -		};
      -
      -reports:
      -  cfengine_3::
      -    "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
      +      "rootprocs",
      +      "otherprocs",
      +      "diskfree",
      +      "loadavg",
      +      "smtp_$(inout)",  #
      +      "www_$(inout)",   # look here
      +      "wwws_$(inout)"   #
      +    };
      +
      +  reports:
      +    cfengine_3::
      +      "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
       }
       ```
       
      @@ -174,28 +173,35 @@ example above is exactly the same as if we had said the following:
       ```cf3
       bundle agent iteration3b
       {
      -vars:
      -    "stats" slist => { "value", "av", "dev" };
      -
      -    "monvars" slist => {
      -		"rootprocs",	"otherprocs",
      -		"diskfree",
      -		"loadavg",
      -		"smtp_in",
      -		"www_in",	"wwws_in"
      -		};
      -
      -    "monvars" slist => {
      -		"rootprocs",	"otherprocs",
      -		"diskfree",
      -		"loadavg",
      -		"smtp_out",
      -		"www_out",	"wwws_out"
      -		};
      -
      -reports:
      -  cfengine_3::
      -    "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
      +  vars:
      +    "stats"
      +      slist => { "value", "av", "dev" };
      +
      +    "monvars"
      +      slist => {
      +        "rootprocs",
      +        "otherprocs",
      +        "diskfree",
      +        "loadavg",
      +        "smtp_in",
      +        "www_in",
      +        "wwws_in"
      +      };
      +
      +    "monvars"
      +      slist => {
      +        "rootprocs",
      +        "otherprocs",
      +        "diskfree",
      +        "loadavg",
      +        "smtp_out",
      +        "www_out",
      +        "wwws_out"
      +      };
      +
      +  reports:
      +    cfengine_3::
      +      "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
       }
       ```
       
      @@ -206,20 +212,23 @@ it will generate an error, because the second promise on the variable monvars
       will overwrite the value promised in the first promise! All that we will see in
       the reports are the second definition of the monvars list.
       
      -# Fixing Iterating across nested lists
      +## Fixing iterating across nested lists
       
       ```cf3
       bundle agent iteration3c
       {
      -vars:
      -    "stats" slist => { "value", "av", "dev" };
      -    "inout" slist => { "in", "out" };
      -
      -    "monvars_$(inout)" slist => {
      -                                "smtp_$(inout)",  #
      -                                "www_$(inout)",   # look here
      -                                "wwws_$(inout)"   #
      -                                };
      +  vars:
      +    "stats"
      +      slist => { "value", "av", "dev" };
      +    "inout"
      +      slist => { "in", "out" };
      +
      +    "monvars_$(inout)"
      +      slist => {
      +        "smtp_$(inout)",  #
      +        "www_$(inout)",   # look here
      +        "wwws_$(inout)"   #
      +      };
       
       reports:
         cfengine_3::
      @@ -234,7 +243,7 @@ you. Note that we had to explicitly refer to the two variables that we created:
       `$(monvars_in)` and `$(monvars_out)`, and specifying more will get very messy
       very quickly. However, the next sections show an easier-to-read workaround.
       
      -# Iterating across multiple lists, revisted
      +## Iterating across multiple lists, revisted
       
       When a list variable is referenced as a scalar variable (that is, when the list
       variable is referenced as `$(list)`) instead of as a list (using `@(list)`),
      @@ -259,7 +268,7 @@ vars:
       
       commands:
           "/bin/echo ${letters}, ${digits}+${digits}, "
      -	args => "${letters} and ${symbols}'";
      +      args => "${letters} and ${symbols}'";
       }
       ```
       
      @@ -278,27 +287,19 @@ symbols:
       ```cf3
       bundle agent iteration4b
       {
      -commands:
      -    "/bin/echo a, 1+1, "
      -	args => "a and @";
      -    "/bin/echo b, 1+1, "
      -	args => "b and @";
      -    "/bin/echo a, 2+2, "
      -	args => "a and @";
      -    "/bin/echo b, 2+2, "
      -	args => "b and @";
      -    "/bin/echo a, 1+1, "
      -	args => "a and #";
      -    "/bin/echo b, 1+1, "
      -	args => "b and #";
      -    "/bin/echo a, 2+2, "
      -	args => "a and #";
      -    "/bin/echo b, 2+2, "
      -	args => "b and #";
      +  commands:
      +    "/bin/echo a, 1+1, " args => "a and @";
      +    "/bin/echo b, 1+1, " args => "b and @";
      +    "/bin/echo a, 2+2, " args => "a and @";
      +    "/bin/echo b, 2+2, " args => "b and @";
      +    "/bin/echo a, 1+1, " args => "a and #";
      +    "/bin/echo b, 1+1, " args => "b and #";
      +    "/bin/echo a, 2+2, " args => "a and #";
      +    "/bin/echo b, 2+2, " args => "b and #";
       }
       ```
       
      -# Nesting promises workaround
      +## Nesting promises workaround
       
       Recall the problem of nesting iterations, we can now see how to repair our
       error. The key is to ensure that there is a distinct and unique promise created
      @@ -308,21 +309,27 @@ solve the problem of listing the input and output packet counts:
       ```cf3
       bundle agent iteration5a
       {
      -vars:
      -    "stats" slist => { "value", "av", "dev" };
      -    "inout" slist => { "in", "out" };
      -    "io_names" slist => { "smtp", "www", "wwws" };
      -    "io_vars[$(io_names)_$(inout)]" int => "0";
      -    "monvars" slist => {
      -		"rootprocs",	"otherprocs",
      -		"diskfree",
      -		"loadavg",
      -		getindices("io_vars")
      -		};
      -
      -reports:
      -  cfengine_3::
      -    "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
      +  vars:
      +    "stats"
      +      slist => { "value", "av", "dev" };
      +    "inout"
      +      slist => { "in", "out" };
      +    "io_names"
      +      slist => { "smtp", "www", "wwws" };
      +    "io_vars[$(io_names)_$(inout)]"
      +      int => "0";
      +    "monvars"
      +      slist => {
      +        "rootprocs",
      +        "otherprocs",
      +        "diskfree",
      +        "loadavg",
      +        getindices("io_vars")
      +      };
      +
      +  reports:
      +    cfengine_3::
      +      "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
       }
       ```
       
      @@ -377,28 +384,34 @@ following:
       ```cf3
       bundle agent iteration5b
       {
      -vars:
      -    "stats" slist => { "value", "av", "dev" };
      -    "inout" slist => { "in", "out" };
      -    "io_names" slist => { "smtp", "www", "wwws" };
      -    "io_vars[$(io_names)_$(inout)]" string => "$(io_names)_$(inout)";
      -    "monvars" slist => {
      -		"rootprocs",	"otherprocs",
      -		"diskfree",
      -		"loadavg",
      -		@(io_vars)
      -		};
      -
      -reports:
      -  cfengine_3::
      -    "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
      +  vars:
      +    "stats"
      +      slist => { "value", "av", "dev" };
      +    "inout"
      +      slist => { "in", "out" };
      +    "io_names"
      +      slist => { "smtp", "www", "wwws" };
      +    "io_vars[$(io_names)_$(inout)]"
      +      string => "$(io_names)_$(inout)";
      +    "monvars"
      +      slist => {
      +        "rootprocs",
      +        "otherprocs",
      +        "diskfree",
      +        "loadavg",
      +        @(io_vars)
      +      };
      +
      +  reports:
      +    cfengine_3::
      +      "mon.$(stats)_$(monvars) is $(mon.$(stats)_$(monvars))";
       }
       ```
       
       However, this is wrong. We cannot use `@(io_vars)`, because `io_vars` is not a
       list, it is an array! You can only use the `@` dereferencing sigil on lists.
       
      -# The power of iteration in CFEngine
      +## The power of iteration in CFEngine
       
       Iteration and abstraction are power tools in CFEngine. In closing, consider the
       following simple and straightforward example, where we report on all of the
      @@ -407,42 +420,56 @@ monitoring variables available to us in CFEngine:
       ```cf3
       bundle agent iteration6
       {
      -vars:
      -    "stats" slist => {"value", "av", "dev"};
      -
      -    "inout" slist => {"in", "out"};
      -    "io_names" slist => {
      -		"netbiosns", "netbiosdgm", "netbiosssn",
      -		"irc",
      -		"cfengine",
      -		"nfsd",
      -		"smtp",
      -		"www",		"wwws",
      -		"ftp",
      -		"ssh",
      -		"dns",
      -		"icmp", 	"udp",
      -		"tcpsyn",	"tcpack",	"tcpfin",	"tcpmisc"
      -		};
      -    "io_vars[$(io_names)_$(inout)]" string => "$(io_names)_$(inout)";
      -
      -    "n" slist => {"0", "1", "2", "3"};
      -    "n_names" slist => {
      -		"temp",
      -		"cpu"
      -		};
      -    "n_vars[$(n_names)$(n)]" string => "$(n_names)$(n)";
      -
      -    "monvars" slist => {
      -		"rootprocs",	"otherprocs",
      -		"diskfree",
      -		"loadavg",
      -		"webaccess",	"weberrors",
      -		"syslog",
      -		"messages",
      -		getindices("io_vars"),
      -		getindices("n_vars")
      -		};
      +  vars:
      +    "stats"
      +      slist => {"value", "av", "dev"};
      +    "inout"
      +      slist => {"in", "out"};
      +    "io_names"
      +      slist => {
      +        "netbiosns",
      +        "netbiosdgm",
      +        "netbiosssn",
      +        "irc",
      +        "cfengine",
      +        "nfsd",
      +        "smtp",
      +        "www",
      +        "wwws",
      +        "ftp",
      +        "ssh",
      +        "dns",
      +        "icmp",
      +        "udp",
      +        "tcpsyn",
      +        "tcpack",
      +        "tcpfin",
      +        "tcpmisc"
      +      };
      +    "io_vars[$(io_names)_$(inout)]"
      +      string => "$(io_names)_$(inout)";
      +    "n"
      +      slist => {"0", "1", "2", "3"};
      +    "n_names"
      +      slist => {
      +        "temp",
      +        "cpu"
      +      };
      +    "n_vars[$(n_names)$(n)]"
      +      string => "$(n_names)$(n)";
      +    "monvars"
      +      slist => {
      +        "rootprocs",
      +        "otherprocs",
      +        "diskfree",
      +        "loadavg",
      +        "webaccess",
      +        "weberrors",
      +        "syslog",
      +        "messages",
      +        getindices("io_vars"),
      +        getindices("n_vars")
      +      };
       
       reports:
         cfengine_3::
      @@ -457,7 +484,7 @@ reports promise and intelligent use of lists and arrays, we are able to report
       on every one of the 3*(8+2*18+4*2)==156 monitor variables. And to change the
       format of every report, we will only have a single statement to change.
       
      -# Summary of iteration
      +## Summary of iteration
       
       Used judiciously and intelligently, iterators are a powerful way of expressing
       patterns. They enable you to abstract out the concepts from the nitty-gritty
      diff --git a/resources/additional-topics/itil.markdown b/resources/additional-topics/itil.markdown
      index 98219db2a..d87ac6e15 100644
      --- a/resources/additional-topics/itil.markdown
      +++ b/resources/additional-topics/itil.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: ITIL
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What it ITIL?
      +## What it ITIL?
       
       
       The IT Infrastructure Library (ITIL) is a set of human management practices
      @@ -31,7 +30,7 @@ end, depends on the concrete instances of ITIL processes in the respective
       scenario.
       
       
      -# ITIL history and versions
      +## ITIL history and versions
       
       
       ITIL has its roots in the early 1990s, and since then was subject to numerous
      @@ -49,7 +48,7 @@ improvement. In the following, we run through the basics of both versions,
       highlighting commonalities and differences.
       
       
      -# Basics
      +## Basics
       
       
       ITIL is an attempt to implement theDeming Quality Circleas a model for continual
      @@ -77,7 +76,7 @@ ITIL means to follow the method of Plan-Do-Check-Act:
         In response to the measured quality, start activities for future improvements.
         This step leads into the Plan phase again.
       
      -# Version 2
      +## Version 2
       
       Although ITIL version 3 was released during the summer of 2007, it is its
       predecessor that has achieved great acceptance amongst IT service providers all
      @@ -93,7 +92,7 @@ Financial Management) are supposed to cover IT service planning like resource
       and quality planning, as well as strategies for customer relationships or
       dealing with unpredictable situations.
       
      -# Version 3
      +## Version 3
       
       
       In 2007, version 2 was replaced by its successor version 3, aimed at covering
      @@ -116,7 +115,7 @@ principles. The five service life cycle stages accordant to versin 3 are:
        * Continual Service Improvement: Methods for planning and achieving service
          improvements at regular intervals
       
      -# Service orientation and ITIL
      +## Service orientation and ITIL
       
       Why service and process orientation? What is ITIL trying to do? As we mentioned
       in the introduction, the `top down hierarchical` control view of human
      @@ -132,7 +131,7 @@ predictable and reliable face for business and IT operations so that customers
       feel confidence, without choking the creative process that lies behind the
       design of new services.
       
      -# CFEngine in ITIL clothes?
      +## CFEngine in ITIL clothes?
       
       CFEngine users are interested in the ability to manage, i.e. cope with system
       configuration in a way that enables a business or other organization to do its
      @@ -163,7 +162,7 @@ services are these? We have to think a little sideways to see the relationship.
         enough people and machines to support the processes of deploying and following
         CFEngine's progress.
       
      -# ITIL processes
      +## ITIL processes
       
       The following management processes are in scope of ITILv3:
       
      @@ -224,20 +223,20 @@ The following management processes are in scope of ITILv3:
       
       * Continual Service Improvement
       
      -## Service Strategy
      +### Service Strategy
       
       Service strategy is about deciding what services you want to formalize. In other
       words, what parts of your system administration tasks can you wrap in procedural
       formalities to ensure that they are carried out most excellently?
       
      -## Service Design
      +### Service Design
       
       Service design is about deciding what will be delivered, when it will be
       delivered, how quickly the service will respond to the needs of its clients etc.
       This stage is probably something of a mental barrier to those who are not used
       to service-oriented thinking.
       
      -## Service Operation
      +### Service Operation
       
       How shall we support service operation? What resources do we need to provide,
       both human and computer? Can we be certain of having these resources at all
      @@ -247,7 +246,7 @@ possible misunderstanding. Successfully running services can be more complex at
       task than we expect, and this is why it is useful to formalize them in an ITIL
       fashion.
       
      -## Continual Service Improvement
      +### Continual Service Improvement
       
       Continual improvement is quite self-explanatory. We are obviously interested in
       learning from our mistakes and improving the quality and efficiency by which we
      @@ -259,9 +258,7 @@ mean regular on a time-scale that is representative for the service being
       provided, e.g. reviews once per week, once per month? No one can tell you about
       your needs. You have to decide this from local needs.
       
      -
      -# Tool Support
      -
      +## Tool support
       
       In the field of tool support for IT Service Management accordant to ITIL,
       various white papers and studies have been published. In addition, there are
      @@ -294,7 +291,7 @@ we must show:
       * Which parts (processes and activities) of ITIL can be (partially) supported by
         CFEngine, and how.
       
      -# Which ITIL processes apply to CFEngine?
      +## Which ITIL processes apply to CFEngine?
       
       ![ITIL and CFEngine](./itil-cfengine.png)
       
      @@ -353,7 +350,7 @@ provision.
       * Incident and problem management
       * Service Level Management (SLM)
       
      -## ITIL Configuration Management (CM)
      +### ITIL Configuration Management (CM)
       
       Perhaps the most obvious example is the term configuration management.
       
      @@ -422,7 +419,7 @@ system.
       
       {% endcomment %}
       
      -## Change management in the enterprise
      +### Change management in the enterprise
       
       If we make changes to a technical installation, or even a business process, this
       can affect the service that customers experience. Major changes to service
      @@ -434,7 +431,7 @@ The decision to make a change is more than a single person should usually make
       alone (see the CFEngine Special Topics Guide on Change Management). ITIL
       recommends an advisory board for changes.
       
      -## Change management vs convergence
      +### Change management vs convergence
       
       We should be especially careful here to decide what we mean by change. ITIL
       assumes a traditional model of change management that CFEngine does not
      @@ -462,7 +459,7 @@ goal to be achieved between changes. An important thing to realize about
       including changes of external circumstances is that you cannot "roll back"
       circumstances to an earlier state - they are beyond our control.
       
      -## Release management
      +### Release management
       
       
       A release in ITIL is a collection of authorized changes to a system. One part of
      @@ -476,7 +473,7 @@ scheduling the release, i.e. everything to do with the release process except
       the explicit implementation of it. Deployment or rollout describe the physical
       movement of configuration items as part of a release process.
       
      -## Incident and problem management
      +### Incident and problem management
       
       ITIL distinguishes betweenincidentsandproblems. An incident is an event that
       might be problematic, but in general would observe incidents over some length of
      @@ -498,7 +495,7 @@ Changes can introduce new incidents. An integrated way to make the tracking of
       cause and effect easier is clearly helpful. If we are the cause of our own
       problems, we are in trouble!
       
      -## Service Level Management (SLM)
      +### Service Level Management (SLM)
       
       
       Also loosely referred to as Quality of Service. This is the process of making
      @@ -506,7 +503,7 @@ sure that Service Level Promises are kept, or Service Level Agreements (SLA) are
       adhered to. We must assess the impact of changes on the ability to deliver on
       promises.
       
      -# Using CFEngine to implement ITIL objectives
      +## Using CFEngine to implement ITIL objectives
       
       
       How does CFEngine fit into the management of a service organization? There are
      @@ -532,7 +529,7 @@ CFEngine can manage itself as well as other resources: itself, its software, its
       policy and the resulting plans for the configuration of the system. In other
       words, CFEngine is itself part of the infrastructure that we might change.
       
      -# How can CFEngine or promises help an enterprise
      +## How can CFEngine or promises help an enterprise
       
       
       Traditional methods of managing IT infrastructure involve working from crisis to
      @@ -575,7 +572,7 @@ generality by making this assumption.
       In other words, OO is a design methodology with a philosophy, whereas promises
       are a model for an arbitrary existing system.
       
      -# What is maintenance?
      +## What is maintenance?
       
       Maintenance is a process that ITIL does not formally spend any time on
       explicitly, but it is central to real-world quality control.
      @@ -606,7 +603,7 @@ against. CFEngine is about this process of Maintenance. We call it "convergence"
       to the ideal state, where the ideal state is the specified version release. Keep
       this in mind as you read about ITIL change management.
       
      -# ITIL and CFEngine Summary
      +## ITIL and CFEngine Summary
       
       ITIL is about processes designed mainly for humans in a workplace. It represents
       a service oriented view of an organization, and as such is more scalable than
      @@ -615,13 +612,13 @@ technology, thus there is some overlap of concepts. Indeed CFEngine is a good
       tool for implementing and assisting in certain ITIL processes, but we believe
       that no automation system can really support what ITIL is about.
       
      -# Appendix A ITIL glossary
      +## Appendix A ITIL glossary
       
       This section lists some of the many terms from ITIL, especially the ISO/IEC
       20000 version of the text, and offers some comments and translations into common
       CFEngine terminology.
       
      -## Active Monitoring
      +### Active Monitoring
       
       Monitoring of a configuration item or IT service that uses automated regular
       checks to discover the current status.
      @@ -630,7 +627,7 @@ CFEngine performs programmed checks of all of its promises each time cfagent is
       started. Cfagent is, in a sense, an active monitor for a set of promises that
       are described in its configuration file.
       
      -## Availability
      +### Availability
       
       The ability of a component or service to perform its required function.
       
      @@ -642,7 +639,7 @@ in a network when remotely connecting to cfservd.
       Intermittency = Successful~ attempts / Total Attempts This is a measurement that
       cfagent automatically makes.
       
      -## Alert
      +### Alert
       
       A warning that a threshold has been reached, something has changed or a failure
       has occurred.
      @@ -650,7 +647,7 @@ has occurred.
       A CFEngine alert fits this description quite well. Most alerts are user-defined,
       but a few are side effects of certain configuration rules.
       
      -## Audit
      +### Audit
       
       A formal inspection and verification to check whether a standard or set of
       guidelines is being followed.
      @@ -660,7 +657,7 @@ However, the data generated by this extra logging information could be collected
       and used in a more detailed examination of CFEngine's operations, suitable for
       use in a formal inspection (e.g. for compliance).
       
      -## Baseline
      +### Baseline
       
       A snapshot of the state of a service or an individual configuration item at a
       point in time
      @@ -671,7 +668,7 @@ the changes we make will not generally be relative to an existing configuration.
       CFEngine encourages users to define the final state (regardless of initial
       state).
       
      -## Benchmark
      +### Benchmark
       
       The recorded state of something at a specific point in time.
       
      @@ -680,14 +677,14 @@ understanding of a "benchmark" is that of a standardized performance measurement
       under special conditions. CFEngine regularly records state and performance data
       in a variety of ways, for example when making file copies.
       
      -## Capability
      +### Capability
       
       The ability of someone or something to carry out an activity.
       
       CFEngine does not use this concept specifically. The notion of a capability is
       terminology used in role-based access control.
       
      -## Change record
      +### Change record
       
       A record containing details of which configuration items are affected and how
       they are affected by an authorized change.
      @@ -703,7 +700,7 @@ daemon. Both of the foregoing messages give only a simple message of actual
       changes. An "audit" promise is a promise to record extensive details about the
       process that cfagent undergoes in its checking of other promises.
       
      -## Chronological Analysis
      +### Chronological Analysis
       
       An analysis based on the timeline of recorded events (used to help identify
       possible causes of problems).
      @@ -711,7 +708,7 @@ possible causes of problems).
       A timeline analysis could easily be carried out based on audit information,
       system logs and cfenvd behavioural records.
       
      -## Configuration
      +### Configuration
       
       A group of configuration items (CI) that work together to deliver an IT service.
       
      @@ -719,7 +716,7 @@ A configuration is the current state of resources on a system. This is, in
       principle, different from the state we would like to achieve, or what has been
       promised.
       
      -## Configuration Item (CI)
      +### Configuration Item (CI)
       
       A component of an infrastructure which is or will be under the control of
       configuration management.
      @@ -727,7 +724,7 @@ configuration management.
       A configuration item is any object making a promise in CFEngine. We often speak
       of the promise object, or "promiser".
       
      -## Configuration Management Database (CMDB)
      +### Configuration Management Database (CMDB)
       
       Database containing all the relevant details of each configuration item and
       details of the important relationships between them.
      @@ -738,7 +735,7 @@ In the future, CFEngine 3 is likely to extend the notion of promises to allow
       more general records of the CMDB kind, but only to the extent that they can be
       verified autonomically.
       
      -## Document
      +### Document
       
       Information and its supporting medium.
       
      @@ -746,14 +743,14 @@ ITIL originally considered a document to be only a container for information. In
       version 3 it considers also the medium on which the data are recorded, i.e. both
       the file and the filesystem on which it resides.
       
      -## Emergency Change
      +### Emergency Change
       
       A change that must be introduced as soon as possible - for example to solve a
       major incident or to implement a critical security patch.
       
       CFEngine has no specific concept for this.
       
      -## Error
      +### Error
       
       A design flaw or malfunction that causes a failure.
       
      @@ -762,7 +759,7 @@ configuration from its promised state. The ITIL meaning of the term would
       translated into "bug in the CFEngine software" or "bug in the promised
       configuration".
       
      -## Event
      +### Event
       
       A change of state that has significance for the management of a configuration
       item or IT service.
      @@ -773,7 +770,7 @@ measure and then classify it into approximate expected states. CFEngine class
       attributes (usually from cfenvd) may be considered as event notifications as
       they change.
       
      -## Exception, Failure, Event, Summary
      +### Exception, Failure, Event, Summary
       
       An event that is generated when a service or device is currently operating
       abnormally.
      @@ -781,7 +778,7 @@ abnormally.
       A state in which configuration policy is violated (could lead to a warning or an
       automated correction).
       
      -## Failure
      +### Failure
       
       Loss of ability to operate to specification or to deliver the required output.
       
      @@ -791,7 +788,7 @@ since promises are only allowed to be made about resources for which we have all
       privileges. Occasionally, environmental issues might interfere and lead to
       failure.
       
      -## Incident
      +### Incident
       
       Any event that is not expected in normal operations and which might cause a
       degradation of service quality.
      @@ -803,7 +800,7 @@ problem on its next invocation round. Events which do not impact promises made
       by CFEngine are of no interest to CFEngine, since autonomy means it cannot be
       responsible for anything beyond its own promises.
       
      -## Monitoring
      +### Monitoring
       
       Repeated observation of a configuration item, IT service or process in order to
       detect events and ensure that the current status is known.
      @@ -811,7 +808,7 @@ detect events and ensure that the current status is known.
       CFEngine incorporates a number of different kinds of monitoring, including
       monitoring of kept configuration-promises and passive monitoring of behaviour.
       
      -## Passive Monitoring
      +### Passive Monitoring
       
       Monitoring of a configuration item or IT service that relies on an alert or
       notification to discover the current status.
      @@ -821,7 +818,7 @@ related behaviour and learns about it. It assumes that there is likely to be a
       weekly periodicity in the data in order to best handle its statistical
       inference.
       
      -## Policy
      +### Policy
       
       Formally documented management expectations and intentions. Policies are used to
       direct decisions, and to ensure consistent and appropriate development and
      @@ -836,7 +833,7 @@ make identical promises. Any resource can play a number of roles. Decisions in
       CFEngine are made entirely on the basis of the result of monitoring a host
       environment.
       
      -## Proactive Monitoring, Problem, Policy, Summary
      +### Proactive Monitoring, Problem, Policy, Summary
       
       Monitoring that looks for patterns of events to predict possible future
       failures.
      @@ -844,7 +841,7 @@ failures.
       All CFEngine monitoring is pro-active in the sense that it can lead to automated
       follow-up actions.
       
      -## Problem
      +### Problem
       
       Unknown underlying cause of one or more incidents.
       
      @@ -852,7 +849,7 @@ A repeated deviation from policy that suggests a change of policy or specific
       counter-measures. A promise needs to be reconsidered or new promises are
       required.
       
      -## Promise, Reactive Monitoring, Problem, Summary
      +### Promise, Reactive Monitoring, Problem, Summary
       
       ITIL does not define this term, although promises are deployed in various ways -
       for instance in terms of cooperation, communication interfaces within or between
      @@ -863,7 +860,7 @@ A promise in CFEngine is a single rule in the CFEngine language. The promiser is
       the resource whose properties are described, and the promisee is implicitly the
       CFEngine monitor.
       
      -## Reactive Monitoring
      +### Reactive Monitoring
       
       Monitoring that takes action in response to an event - for example submitting a
       batch job when the previous job completes, or logging an incident when an error
      @@ -876,14 +873,14 @@ any observable condition discernable by CFEngine's monitor. CFEngine is not
       usually considered event driven however, since it does not react "as soon as
       possible" but at programmed intervals.
       
      -## Record
      +### Record
       
       Information in readable form that is maintained by the service provider about
       operations.
       
       A log entry or database item.
       
      -## Recovery
      +### Recovery
       
       Returning a Configuration Item or an IT service to a working state. Recovering
       of an IT service often includes recovering data to a known consistent state.
      @@ -894,7 +891,7 @@ principle) on every invocation. CFEngine always returns to a known state, due to
       the property of "convergence". There is no distinction between the concepts of
       repair, recovery or remediation.
       
      -## Remediation
      +### Remediation
       
       Recovery to a known state after a failed change or release.
       
      @@ -907,7 +904,7 @@ repair, recovery or remediation.
       However, this concept is like the notion of "rollback" which often involves a
       more significant restoration of a system from backup. This is discussed later.
       
      -## Repair
      +### Repair
       
       The replacement or correction of a failed configuration item.
       
      @@ -917,14 +914,14 @@ principle) on every invocation. CFEngine always returns to a known state, due to
       the property of "convergence". There is no distinction between the concepts of
       repair, recovery or remediation.
       
      -## Release, Request for Change, Repair, Summary
      +### Release, Request for Change, Repair, Summary
       
       A collection of new or changed configuration items that are introduced together.
       
       An instantiation of the entire CFEngine system under a specific version of a
       policy, i.e. a specific set of promises.
       
      -## Request for Change
      +### Request for Change
       
       A form to be completed requesting the need for change. This is to be followed
       up.
      @@ -937,7 +934,7 @@ sense is part of an organizational process that goes beyond CFEngine's level of
       jurisdiction. This is an example of what ITIL adds to the autonomous CFEngine
       model.
       
      -## Abandon Autonomy?
      +### Abandon Autonomy?
       
       Why not simply abandon autonomy of machines if this seems to interfere with the
       need for organizational change? There are good reasons why autonomy is the
      @@ -951,14 +948,14 @@ discusses how they will change their pattern of collaboration. There is no point
       in this process at which it is necessary for one of the systems to give up its
       autonomy.
       
      -## Resilience
      +### Resilience
       
       The ability of a configuration item or IT service to resist failure or to
       recover quickly following a failure.
       
       CFEngine's purpose is to make a system resilient to unpredictable change.
       
      -## Restoration
      +### Restoration
       
       Actions taken to return an IT service to the users after repair and recovery
       from an incident.
      @@ -973,7 +970,7 @@ However, this concept seems to suggest a more catastrophic failure which often
       involves a more significant restoration of a system from backup. This is
       discussed later.
       
      -## Role
      +### Role
       
       A set of responsibilities, activities and authorities granted to a person or a
       team. Roles are defined in processes.
      @@ -983,13 +980,13 @@ type of role played by the class is determined by the nature of the promise they
       make. e.g. a promise to run a web server would naturally lead to the role "web
       server".
       
      -## Service desk
      +### Service desk
       
       Interface between users and service provider.
       
       A help desk. This is not formally part of CFEngine's tool set.
       
      -## Service Level Agreement
      +### Service Level Agreement
       
       A written agreement between the service provider that documents agreed services,
       levels and penalties for non-compliance.
      @@ -999,11 +996,11 @@ of those promises by the client. If we assume that the users are satisfied with
       out policies, then an SLA can be interpreted as a combination of a configuration
       policy (configuration service promises), and the CFEngine execution schedule.
       
      -## Service Management
      +### Service Management
       
       The management of services.
       
      -## Warning
      +### Warning
       
       An event that is generated when a service or device is approaching its threshold.
       
      diff --git a/resources/additional-topics/modularity.markdown b/resources/additional-topics/modularity.markdown
      index 97cdb9810..70ec67fab 100644
      --- a/resources/additional-topics/modularity.markdown
      +++ b/resources/additional-topics/modularity.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Modularity and Orchestrating System Policy
      +title: Modularity and orchestrating system policy
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is modularity?
      +## What is modularity?
       
       Modularity is the ability to separate concerns within a total process, and hide
       the details of the different concerns in different containers. In CFEngine, this
      @@ -15,7 +14,7 @@ and turned into generic components that offer a service. We often talk about
       black boxes, grey boxes or white boxes depending on the extent to which the user
       of a service can see the details within the containers.
       
      -# What is orchestration?
      +## What is orchestration?
       
       Orchestration is the ability to coordinate many different processes in time and
       space, around a system, so that the sum of those processes yields a harmonious
      @@ -36,7 +35,7 @@ information from the policy server (conductor). The coupling between the agents
       is weak - there is slack that makes the behaviour robust to minor errors in
       communication or timing.
       
      -# How does CFEngine deal with modularity and orchestration?
      +## How does CFEngine deal with modularity and orchestration?
       
       Promise Theory provides simple principles for hiding details: agents are
       considered to reveal a kind of service interface to peers, that is advertised by
      @@ -55,15 +54,15 @@ might also need to cooperate because they provide services to one another. The
       principles are the same in both cases, but the confusion between them is
       typically the reason why large systems do not scale well.
       
      -# Levels of policy abstraction
      +## Levels of policy abstraction
       
       CFEngine offers a number of layers of abstraction. The most fundamental atom in
       CFEngine is the promise. Promises can be made about many system issues, and you
       described in what context promises are to be kept.
       
      -## Menu level
      +### Menu level
       
      -At this high level, a user `selects' from a set of pre-defined `services' (or
      +At this high level, a user _selects_ from a set of pre-defined _services_ (or
       bundles in CFEngine parlance). In commercial editions, users may view the set of
       services as a Service Catalogue, from which each host selects its roles. The
       selection is not made by every host, rather one places hosts into roles that
      @@ -98,7 +97,7 @@ The resulting menu of services can be browsed in the Mission Portal interface.
       A human-readable Service Catalogue generated from technical specifications shows
       what goals are being attended to automatically
       
      -## Bundle level
      +### Bundle level
       
       At this level, users can switch on and off predefined features, or re-use
       standard methods, e.g. for editing files:
      @@ -117,7 +116,7 @@ bundlesequence => {
       
       The set of bundles that can be selected from is extensible by the user.
       
      -## Promise level
      +### Promise level
       
       This is the most detailed level of configuration, and gives full convergent
       promise behaviour to the user. At this promise level, you can specificy every
      @@ -146,7 +145,7 @@ files:
       }
       ```
       
      -## Spread-sheet level (data-driven)
      +### Spread-sheet level (data-driven)
       
       CFEngine community and commercial editions support a kind of spreadsheet. In a
       spreadsheet approach, you create only the data to be inserted into predefined
      @@ -154,7 +153,7 @@ promises. The data are entered in tabular form, and may be browsed in the web
       interface. This form of entry is preferred in some environments, especially on
       the Windows platform.
       
      -# Is CFEngine patch-oriented or package-oriented?
      +## Is CFEngine patch-oriented or package-oriented?
       
       Some system management products are patching systems. They package lumps of
       software and configuration along with scripts. If something goes wrong they
      @@ -171,7 +170,7 @@ one bit of a flag in each file in a set of directories. The power to express
       sophisticated patterns is what makes CFEngine's approach both non-intrusive and
       robust.
       
      -# High level services in CFEngine
      +## High level services in CFEngine
       
       CFEngine is designed to handle high level simplicity (without sacrificing low
       level capability) by working with configuration patterns, after all
      @@ -250,7 +249,7 @@ services:
       }
       ```
       
      -# Hiding details
      +## Hiding details
       
       Resource abstraction, or hiding system specific details inside a kind of
       grey-box, is just another service as far as CFEngine is concerned - and we
      @@ -259,7 +258,7 @@ generally map services to bundles.
       Many system variables are discovered automatically by CFEngine and provided "out
       of the box", e.g. the location of the filesystem table might be /etc/fstab, or
       /etc/vfstab or even /etc/filesystems, but CFEngine allows you to refer simply to
      -**$(sys.fstab)**. Soft-coded abstraction needs cannot be discovered by the
      +`$(sys.fstab)`. Soft-coded abstraction needs cannot be discovered by the
       system however. So how do we create this mythical resource abstraction layer? It
       is simple. Elsewhere we have defined basic settings.
       
      @@ -297,7 +296,7 @@ decisions, meaning that minor changes in operating system versions require basic
       re-coding of the software. CFEngine does not make decisions for you without your
       permission.
       
      -# Black, grey and white box encapsulation in CFEngine
      +## Black, grey and white box encapsulation in CFEngine
       
       CFEngine's ability to abstract system decisions as promises also applies to
       bundles of promises. After all, we can package promises as bumper compendia for
      @@ -358,7 +357,7 @@ commands:
       }
       ```
       
      -# Bulk operations are handled by repeating patterns over lists
      +## Bulk operations are handled by repeating patterns over lists
       
       The power of CFEngine is to be able to handle lists of similar patterns in a
       powerful way. You can also wrap the whole experience in a method-bundle, and we
      @@ -429,7 +428,7 @@ reports:
       }
       ```
       
      -# Ordering operations in CFEngine
      +## Ordering operations in CFEngine
       
       Ordering of operations is less important than you probably think. We are taught
       to think of computing as an linear sequence of steps, but this ignores a crucial
      @@ -473,7 +472,7 @@ more sophisticated ways) using methods promises. Methods promises are simply
       promises to re-use bundles, possibly with different parameters.
       
       The default behaviour is to retain the order of these promises; the effect is to
      -`execute' these bundles in the assumed order:
      +_execute_ these bundles in the assumed order:
       
       ```cf3
       bundle agent a_bundle_subsequence
      @@ -556,7 +555,7 @@ Q: ".../bin/echo four": four
       Q: ".../bin/echo five": five
       ```
       
      -# Distributed Orchestration between hosts with CFEngine Enterprise
      +## Distributed Orchestration between hosts with CFEngine Enterprise
       
       CFEngine Enterprise edition adds many powerful features to CFEngine, including a
       decentralized approach to coordinating activities across multiple hosts. Some
      @@ -570,7 +569,7 @@ location, but this has two problems:
       With CFEngine Nova there are are both decentralized network approaches to this
       problem, and probabilistic methods that do not require the network at all.
       
      -## Basic communication methods for orchestration
      +### Basic communication methods for orchestration
       
       The two examples below illustrate the basic syntax constructions for
       communication using systems. We can pass class data and variable data between
      @@ -739,7 +738,7 @@ R: GOT knowedge scalar value of my test_scalar, can expand variables here - cflu
       R: GOT persistent scalar 1
       ```
       
      -## Run job or reboot only if n out m systems are running
      +### Run job or reboot only if n out m systems are running
       
       The ability to base local promises on global knowledge seems superficially
       attractive in some cases. As a strategy this way of thinking requires a lot of
      @@ -825,10 +824,10 @@ access:
       }
       ```
       
      -# The self-healing chain - inverse Dominoes
      +## The self-healing chain - inverse Dominoes
       
       A self-healing chain is the opposite of a dominoe event. If a part of the chain
      -is `down', it will be revived. If these events depend on one another, then the
      +is _down_, it will be revived. If these events depend on one another, then the
       resuscitation of this part which cause all of the subsequent parts to be
       repaired too.
       
      @@ -1017,7 +1016,7 @@ R: tier 3 is ok
       R: The Tower is standing
       ```
       
      -## A Domino sequence
      +### A Domino sequence
       
       A different kind of orchestration is a domino cascade, that starts from some
       initial trigger, and causes a change in one host that causes a change in the
      @@ -1207,7 +1206,7 @@ chain multiplied by the run-interval, if normal cf-execd splaytime is used.
       Without any splaying, the average time will be the run interval multiplied by
       the chain length. The completion time could be increased by using cf-runagent.
       
      -## A Chinese Dragon star pattern
      +### A Chinese Dragon star pattern
       
       The Chinese dragon darts back and forth between different hosts, forming a chain
       of events, and leaving a trail behind it. This pattern is much like the Domino
      diff --git a/resources/additional-topics/open-nebula.markdown b/resources/additional-topics/open-nebula.markdown
      index b2bafc8b3..7ad1015b1 100644
      --- a/resources/additional-topics/open-nebula.markdown
      +++ b/resources/additional-topics/open-nebula.markdown
      @@ -3,17 +3,16 @@ layout: default
       title: Using CFEngine with Open Nebula
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is Open Nebula?
      +## What is Open Nebula?
       
       Open Nebula is an Open Source framework for Cloud Computing that aims to become
       an industry standard. The project is designed to be scalable and offer
       compatibility with Amazon EC2 the Open Cloud Computing Interface (OCCI). Open
       Nebula is used as a cloud controller in a number of large private clouds.
       
      -# How can CFEngine work with Open Nebula?
      +## How can CFEngine work with Open Nebula?
       
       CFEngine is a lifecycle management tool that can be integrated with a Cloud
       Computing framework in a number of ways. Of the four phases of the computer
      @@ -48,7 +47,7 @@ Open Nebula's focus is on managing the deployment and recycling of the computing
       infrastructure. CFEngine picks up where Open Nebula leaves off and manages the
       dynamic lifecycle of software, applications and runtime state.
       
      -# Example Setup
      +## Example setup
       
       This guide is based on an example setup provding a framework to demonstrate how
       CFEngine can be used to automate Open Nebula configuration. The following
      @@ -70,7 +69,7 @@ cluster-node.
       
       ![Open Nebula Architecture](./open-nebula-architecture.png)
       
      -##  Installation and dependancy configuration
      +###  Installation and dependancy configuration
       
       
       First we can classify the physical machines in this case by IP address:
      @@ -111,28 +110,27 @@ list and use the CFEngine standard library package promises to install them:
       
       ```cf3
       vars:
      -
      -"front_end_deps" slist => {
      -                          "libcurl3",
      -                          "libmysqlclient16",
      -                          "libruby1.8",
      -                          "libsqlite3-ruby",
      -                          "libsqlite3-ruby1.8",
      -                          "libxmlrpc-c3",
      -                          "libxmlrpc-core-c3",
      -                          "mysql-common",
      -                          "ruby",
      -                          "ruby1.8",
      -                          "nfs-kernel-server"
      -                          };
      -"cluster_node_deps" slist => {
      -			"ruby",
      -			"kvm",
      -			"libvirt-bin",
      -			"ubuntu-vm-builder",
      -			"nfs-client",
      -			"kvm-pxe"
      -			};
      +  "front_end_deps" slist => {
      +    "libcurl3",
      +    "libmysqlclient16",
      +    "libruby1.8",
      +    "libsqlite3-ruby",
      +    "libsqlite3-ruby1.8",
      +    "libxmlrpc-c3",
      +    "libxmlrpc-core-c3",
      +    "mysql-common",
      +    "ruby",
      +    "ruby1.8",
      +    "nfs-kernel-server"
      +  };
      +  "cluster_node_deps" slist => {
      +    "ruby",
      +    "kvm",
      +    "libvirt-bin",
      +    "ubuntu-vm-builder",
      +    "nfs-client",
      +    "kvm-pxe"
      +  };
       ```
       
       Promises to perform dependency installation:
      @@ -165,8 +163,8 @@ times:
       front_end::
       
       ensure_opennebula_running::
      -        ".*oned.*",
      -		restart_class => "start_oned";
      +  ".*oned.*",
      +    restart_class => "start_oned";
       ```
       
       Resulting in:
      @@ -175,10 +173,10 @@ Resulting in:
       ```cf3
       commands:
       
      -start_oned::
      -	"/usr/bin/one start",
      -		comment => "Execute the opennebula daemon",
      -		contain => oneadmin;
      +  start_oned::
      +    "/usr/bin/one start",
      +      comment => "Execute the opennebula daemon",
      +      contain => oneadmin;
       ```
       
       
      @@ -189,9 +187,9 @@ package:
       ```cf3
       commands:
       
      -front_end.!opennebula_installed::
      -	"/usr/bin/dpkg -i /root/opennebula_2.0-1_i386.deb",
      -	comment => "install opennebula package if it isnt already";
      +  front_end.!opennebula_installed::
      +    "/usr/bin/dpkg -i /root/opennebula_2.0-1_i386.deb",
      +      comment => "install opennebula package if it isnt already";
       ```
       
       This promise points to the Open Nebula package file in /root/. To prevent
      @@ -202,7 +200,7 @@ in existence:
       ```cf3
       classes:
       
      -	"opennebula_installed" or => {fileexists("/etc/one/oned.conf")};
      +  "opennebula_installed" or => {fileexists("/etc/one/oned.conf")};
       ```
       
       Open nebula requires a privileged user "oneadmin" to issue commands. In order to
      @@ -210,7 +208,7 @@ have CFEngine perform these commands with the correct privileges we can use the
       contain body by appending the following to commands promises:
       
       ```cf3
      -	contain => oneadmin
      +contain => oneadmin
       ```
       
       
      @@ -219,8 +217,8 @@ This will in turn apply owner and group permissions of the oneadmin user:
       ```cf3
       body contain oneadmin
       {
      -exec_owner => "oneadmin";
      -exec_group => "oneadmin";
      +  exec_owner => "oneadmin";
      +  exec_group => "oneadmin";
       }
       ```
       
      @@ -271,46 +269,46 @@ NFS promise:
       ```cf3
       storage:
       
      -cluster_node::
      -"/var/lib/one",
      -       mount  => nfs("192.168.1.2","/var/lib/one"),
      -       comment => "mount image repo from front end";
      +  cluster_node::
      +    "/var/lib/one",
      +      mount => nfs("192.168.1.2","/var/lib/one"),
      +      comment => "mount image repo from front end";
       ```
       
       Next we will create a directory to hold our virtual machine images:
       
       ```cf3
       "/var/lib/one/images/.",
      -        comment => "create dir in image repo share",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        create => "true";
      +  comment => "create dir in image repo share",
      +  perms => mog("644", "oneadmin", "oneadmin"),
      +  create => "true";
       ```
       
      -## Open Nebula environment configuration
      +### Open Nebula environment configuration
       
       Create the oneadmin bashrc file containing the ONE_XMLRPC environment variable with appropriate permissions:
       
       ```cf3
       files:
      - front_end::
      -  "/var/lib/one/.bashrc"
      -        comment => "setup oneadmin env",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        create => "true",
      -		edit_line => append_if_no_line(
      -			"export ONE_XMLRPC=http://localhost:2633/RPC2");
      +  front_end::
      +    "/var/lib/one/.bashrc"
      +      comment => "setup oneadmin env",
      +      perms => mog("644", "oneadmin", "oneadmin"),
      +      create => "true",
      +      edit_line => append_if_no_line(
      +    "export ONE_XMLRPC=http://localhost:2633/RPC2");
       ```
       
       We also need to create the one_auth file:
       
       ```cf3
       files:
      - front_end::
      -  "/var/lib/one/.one/one_auth",
      -        comment => "create open nebula auth file",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        create => "true",
      -        edit_line => append_if_no_line("username:password");
      +  front_end::
      +    "/var/lib/one/.one/one_auth",
      +      comment => "create open nebula auth file",
      +      perms => mog("644", "oneadmin", "oneadmin"),
      +      create => "true",
      +      edit_line => append_if_no_line("username:password");
       ```
       
       Finally password-less authentication for the oneadmin user:
      @@ -321,21 +319,21 @@ Add key to autorized_keys file:
       files:
         front_end::
           "/var/lib/one/.ssh/authorized_keys",
      -        comment => "copy sshkey to authorized",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        copy_from => local_cp("/var/lib/one/.ssh/id_rsa.pub");
      +      comment => "copy sshkey to authorized",
      +      perms => mog("644", "oneadmin", "oneadmin"),
      +      copy_from => local_cp("/var/lib/one/.ssh/id_rsa.pub");
       ```
       
       Disable known hosts prompt:
       
       ```cf3
       front_end::
      -"/var/lib/one/.ssh/config",
      -        comment => "disable strict host key checking",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        create => "true",
      -        edit_line => append_if_no_line("Host *
      -        StrictHostKeyChecking no");
      +  "/var/lib/one/.ssh/config",
      +    comment => "disable strict host key checking",
      +    perms => mog("644", "oneadmin", "oneadmin"),
      +    create => "true",
      +    edit_line => append_if_no_line("Host *
      +    StrictHostKeyChecking no");
       ```
       
       Now on the node controller(s) we need to add the oneadmin group and user with
      @@ -344,16 +342,16 @@ group:
       
       ```cf3
       files:
      - node_controller::
      -  "/etc/passwd",
      +  node_controller::
      +    "/etc/passwd",
             comment => "add oneadmin user to node controller",
             edit_line => append_if_no_line("oneadmin:x:999:999::/srv/cloud/one:/bin/bash");
       
      - "/etc/group",
      +    "/etc/group",
             comment => "add oneadmin group to node controller",
             edit_line => append_if_no_line("oneadmin:x:999:");
       
      - "/etc/group",
      +    "/etc/group",
             comment =>"add oneadmin to libvirtd group",
             edit_line => append_user_field("libvirtd","4","oneadmin");
       ```
      @@ -363,12 +361,12 @@ with the front end:
       
       ```cf3
       files:
      - front_end::
      -      "/usr/bin/onehost create 192.168.1.2 im_kvm vmm_kvm tm_nfs",
      -		contain => oneadmin;
      +  front_end::
      +    "/usr/bin/onehost create 192.168.1.2 im_kvm vmm_kvm tm_nfs",
      +      contain => oneadmin;
       ```
       
      -## Network configuration
      +### Network configuration
       
       Before we can create virtual networks we must configure our node controller
       interfaces. In this example we will bridge a virtual interface (vbr0) with eth0.
      @@ -377,32 +375,32 @@ First we define the contents of the interfaces file in a variable:
       ```cf3
       vars:
       "interfaces_contents" slist => {
      -                               "auto lo",
      -                               "iface lo inet loopback",
      -                               "auto vbr0",
      -                               "iface vbr0 inet static",
      -                               "address 192.168.1.2",
      -                               "netmask 255.255.255.0",
      -                               "network 192.168.1.0",
      -                               "broadcast 192.168.1.255",
      -                               "gateway 192.168.1.1",
      -                               "dns-nameservers 192.168.1.1",
      -                               "bridge_ports    eth0",
      -                               "bridge_stp      off",
      -                               "bridge_maxwait  0",
      -                               "bridge_fd       0"
      -                               };
      +  "auto lo",
      +  "iface lo inet loopback",
      +  "auto vbr0",
      +  "iface vbr0 inet static",
      +  "address 192.168.1.2",
      +  "netmask 255.255.255.0",
      +  "network 192.168.1.0",
      +  "broadcast 192.168.1.255",
      +  "gateway 192.168.1.1",
      +  "dns-nameservers 192.168.1.1",
      +  "bridge_ports    eth0",
      +  "bridge_stp      off",
      +  "bridge_maxwait  0",
      +  "bridge_fd       0"
      +};
       ```
       Next we edit the interfaces file to include our new settings:
       
       ```cf3
       files:
      -node_controller::
      -"/etc/network/interfaces",
      -        comment => "ensure bridge for open nebula vm networks",
      -        edit_line => append_if_no_lines($(interfaces_contents)),
      -        create => "true",
      -        perms => mog("644", "root", "root");
      +  node_controller::
      +    "/etc/network/interfaces",
      +      comment => "ensure bridge for open nebula vm networks",
      +      edit_line => append_if_no_lines($(interfaces_contents)),
      +      create => "true",
      +      perms => mog("644", "root", "root");
       ```
       
       And restart networking:
      @@ -410,9 +408,8 @@ And restart networking:
       ```cf3
       commands:
         restart_networking::
      -
           "/etc/init.d/networking restart",
      -       comment => "restart networking";
      +      comment => "restart networking";
       ```
       
       Now we have configured the network bridge we can create an Open Nebula virtual
      @@ -422,10 +419,10 @@ case it is passed as a parameter to the append promise body:
       
       ```cf3
       "/var/lib/one/network.template",
      -        comment => "create lan template",
      -        create => "true",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        edit_line => append_if_no_line("NAME = \"VM LAN\"
      +  comment => "create lan template",
      +  create => "true",
      +  perms => mog("644", "oneadmin", "oneadmin"),
      +  edit_line => append_if_no_line("NAME = \"VM LAN\"
       TYPE = FIXED
       BRIDGE = vbr0
       LEASES = [IP=192.168.1.100]");
      @@ -442,7 +439,7 @@ commands:
               contain => oneadmin;
       ```
       
      -## Virtual machine template configuration
      +### Virtual machine template configuration
       
       This follows the same pattern as virtual network setup. First we create the
       template file:
      @@ -451,10 +448,10 @@ template file:
       files:
       
         "/var/lib/one/vm.template",
      -        comment => "create vm template",
      -        create => "true",
      -        perms => mog("644", "oneadmin", "oneadmin"),
      -        edit_line => append_if_no_line("NAME   = ubuntu-10.04-i386
      +    comment => "create vm template",
      +    create => "true",
      +    perms => mog("644", "oneadmin", "oneadmin"),
      +    edit_line => append_if_no_line("NAME   = ubuntu-10.04-i386
       CPU    = 0.1
       MEMORY = 256
       DISK   = [
      @@ -477,15 +474,15 @@ Now we can launch the virtual machine defined in its template file:
       ```cf3
       commands:
         front_end::
      -      "/usr/bin/onevm create /var/lib/one/vm.template",
      -		contain => oneadmin;
      +    "/usr/bin/onevm create /var/lib/one/vm.template",
      +      contain => oneadmin;
       ```
       
       If we increase the leases in our network template each time the onevm create
       command is issued a new virtual machine will be launched up to the number of
       available leases.
       
      -## Open Nebula Commands
      +### Open Nebula commands
       
       It should be noted that commands, particularly those that are Open Nebula
       specific, will be run each time cf-agent is executed. Since this goes against
      @@ -495,7 +492,7 @@ successfully executed. If this file exists then (or if its time stamp is
       older/newer than some value) the machines classified as having to run the
       command loose that class preventing future execution.
       
      -## Virtual machine configuration
      +### Virtual machine configuration
       
       With CFEngine preinstalled in our virtual machine image we can configure our
       generic image to the required specification on the fly. For community edition we
      @@ -515,19 +512,18 @@ with a meaningful name:
       Now we have define webserver we can simply apply promises to it as if it was any
       other machine for example:
       
      -## Webserver in Open Nebula
      +### Webserver in Open Nebula
       
       First we install apache:
       
       ```cf3
       packages:
      - webserver::
      -
      -   "apache2",
      -	comment => "install apache2 on webserver vm",
      -	package_policy => "add",
      -        package_method => generic,
      -        classes => if_ok("ensure_apache_running");
      +  webserver::
      +    "apache2",
      +      comment => "install apache2 on webserver vm",
      +      package_policy => "add",
      +      package_method => generic,
      +      classes => if_ok("ensure_apache_running");
       ```
       
       Next we ensure it is running
      @@ -535,9 +531,8 @@ Next we ensure it is running
       ```cf3
       processes:
         ensure_apache_running::
      -
      -         ".*apache2.*"
      -                restart_class => "start_apache";
      +    ".*apache2.*"
      +      restart_class => "start_apache";
       ```
       
       If not, the service is restarted
      @@ -562,7 +557,7 @@ files:
            action => u_immediate;
       ```
       
      -# Open Nebula Summary
      +## Open Nebula summary
       
       Now we have a convergent self-repairing, Open Nebula powered private cloud! The
       main benefits in combining CFEngine and Open Nebula are the facility to increase
      diff --git a/resources/additional-topics/orchestration.markdown b/resources/additional-topics/orchestration.markdown
      index bd0a2127b..ee13b927c 100644
      --- a/resources/additional-topics/orchestration.markdown
      +++ b/resources/additional-topics/orchestration.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: Orchestration
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is organizational complexity?
      +## What is organizational complexity?
       
       Complexity is a measure of the amount of information needed to explain
       something. It implies a "mental cost" (and therefore a time and monetary cost)
      @@ -25,7 +24,7 @@ complexity of a system is commonly defined as the length of the shortest
       document that fully describes it. A complex system requires a long document to
       capture its workings; a simple system requires only a short document.
       
      -# What is federation?
      +## What is federation?
       
       A federation is a pattern of organization obtained by merging a number of
       initially independent parts. The implication is that the resulting organization
      @@ -83,7 +82,7 @@ known as "voluntary cooperation" used by CFEngine, which implies that each
       federated part must effectively choose which inputs it is willing to use from
       external parties.
       
      -# The Authority Paradox
      +## The authority paradox
       
       For some, the idea that an organization should be built on voluntary cooperation
       sounds wrong. However, no matter how much we might crave certainty of outcome,
      @@ -136,7 +135,7 @@ No central management of either enterprise or computers can force individual
       agents to comply with their wishes, without their low level consent. The
       perception of authority is thus only a fiction1.
       
      -# The social contract
      +## The social contract
       
       Social contracts lie at the heart of all human and computer organizations. For
       computers these contracts may be as simple as "access control settings",
      @@ -159,7 +158,7 @@ worst lead to the disconnection of decision making from expertise.
       Low level autonomy is a cost saving strategy that reduces the overhead of
       management and improves the link between expertise and action.
       
      -# Service oriented federation
      +## Service oriented federation
       
       Service oriented means business oriented. Let us now consider what this means
       for IT configuration. In particular, how should a CFEngine configuration be
      @@ -167,7 +166,7 @@ structured for an efficient organization? In the examples below, we shall adopt
       a service oriented view, in which an enterprise is organized as a set of
       federated entities, some of whom depend on each other for services.
       
      -# Each part disconnected, providing services
      +## Each part disconnected, providing services
       
       Each federated entity manages its own promises.cf file. Each has, in effect, its
       own independent CFEngine configuration.
      @@ -178,7 +177,7 @@ The configuration may still use resources provided by other entities' machines,
       but the other entities have no influence on the set of promises used to maintain
       any given one.
       
      -# Disconnected parts inheriting a single baseline
      +## Disconnected parts inheriting a single baseline
       
       A more common model for federation is to have a baseline constitution for all
       the parts of the enterprise defined by an umbrella organization. We can refer to
      @@ -246,7 +245,7 @@ must be that their own special promises must not conflict with the global
       infrastructure proposal. So all requirements are met without the need for
       central enforcement.
       
      -# Handling multiple sources
      +## Handling multiple sources
       
       Consider briefly the case in which there is more than one entity offering
       promise proposals. If a part of the federation serves two masters (see
      @@ -261,7 +260,7 @@ make the decision about which of the sources to obey.
       The possiblity of conflict is easily handled in this architecture, because it
       recognizes that the federated entity must be the final arbiter of confict.
       
      -# Global assurance
      +## Global assurance
       
       The lack of a hierarchy has not made information chaotic and disorganized. It
       has only provided a simple means of scalability and conflict resolution.
      @@ -279,7 +278,7 @@ federation according to a single standard3.
       CFEngine allows single-point-of-coodination monitoring of hosts by a variety of
       mechanisms, so that compliance can be assured.
       
      -# Merging and dividing enterprises
      +## Merging and dividing enterprises
       
       Autonomy makes the merging and division of enterprise systems trivial. It is the
       way to enable out-sourcing and in-sourcing.
      @@ -298,7 +297,7 @@ house of cards. Service-oriented systems are loosely coupled. By keeping the
       internal organization of systems as far as possible like independent service
       atoms, you facilitate reorganization by merging and division.
       
      -# Why federation does not reduce predictabilty
      +## Why federation does not reduce predictabilty
       
       The fear that many traditionalists have of federated management is that they
       cannot be certain of the outcome unless they have absolute authority. This fear
      @@ -332,7 +331,7 @@ Rules of thumb for scalable management:
       
       * Trust lowers costs.
       
      -# The benefits of federated management
      +## The benefits of federated management
       
       Hierarchy is familiar, but not essential. A hierarchy is only a so-called
       "spanning tree" for a more general network of relationships. It may be thought
      diff --git a/resources/additional-topics/overlapping-sets.png b/resources/additional-topics/overlapping-sets.png
      index d49360195..cd1f0731f 100644
      Binary files a/resources/additional-topics/overlapping-sets.png and b/resources/additional-topics/overlapping-sets.png differ
      diff --git a/resources/additional-topics/package-management.markdown.breaks_build b/resources/additional-topics/package-management.markdown.breaks_build
      index d6b21217d..a8cc084b6 100644
      --- a/resources/additional-topics/package-management.markdown.breaks_build
      +++ b/resources/additional-topics/package-management.markdown.breaks_build
      @@ -1,6 +1,6 @@
       ---
       layout: default
      -title: Package Management
      +title: Package management
       published: false
       sorting: 80
       tags: [overviews, special topics, guide]
      diff --git a/resources/additional-topics/security.markdown b/resources/additional-topics/security.markdown
      index c71226c99..a76704928 100644
      --- a/resources/additional-topics/security.markdown
      +++ b/resources/additional-topics/security.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Security
       published: True
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
       Diego Zamboni, discusses why CFEngine is a critical component of maintaining IT system security. Many vulnerabilities are directly caused by faulty configurations, so security is closely linked to how well configuration management works.
      @@ -12,7 +11,7 @@ Learn how security has been built into CFEngine architecture and how CFEngine ke
       
       
       
      -## Architecture Principles
      +## Architecture principles
       
       CFEngine is agent based software. It resides on and runs processes on each
       individual computer under its management. That means you do not need to grant
      @@ -113,7 +112,7 @@ and large companies (e.g. formed through acquisition) are typical candidates for
       federated management. Federation is facilitated by a service
       oriented architecture, i.e. a weak coupling.
       
      -## Security Principles
      +## Security principles
       
       ### What is security?
       
      @@ -155,7 +154,7 @@ Infrastructure.
        * Authentication by Public Key is mandatory.
        * Encryption of data transfer is optional.
       
      -## Communication Security
      +## Communication security
       ### TCP wrappers
       
       The right to connect to the server is the first line of defence. CFEngine has
      @@ -290,7 +289,7 @@ firewall security model of trusted/untrusted regions. The firewall does not
       mitigate the responsibility of security every host in a network regardless of
       which side of the firewall it is connected.
       
      -### CFEngine and Firewalls
      +### CFEngine and firewalls
       
       Some users want to use CFEngine's remote copying mechanism through a firewall,
       in particular to update the CFEngine policy on hosts inside a DMZ (so-called
      @@ -324,7 +323,7 @@ processes on the outside of the firewall to receive updated policies from the
       inside of the firewall, information has to traverse the firewall.
       
       * CFEngine trust model
      -* Policy Mirror in the DMZ
      +* Policy mirror in the DMZ
       * Pulling through a wormhole
       
       #### CFEngine trust model
      @@ -361,7 +360,7 @@ latter to offer at this point:
         ludicrous to suggest that an arbitrary employee's machine is more secure than
         an inaccessible host in the DMZ.
       
      -#### Policy Mirror in the DMZ
      +#### Policy mirror in the DMZ
       
       By creating a policy mirror in the DMZ, these issues can be worked around. This
       is the recommended way to copy files, so that normal CFEngine pull methods can
      diff --git a/resources/additional-topics/stigs.markdown b/resources/additional-topics/stigs.markdown
      index c8d05028d..b78c1517c 100644
      --- a/resources/additional-topics/stigs.markdown
      +++ b/resources/additional-topics/stigs.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: STIGs
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# CFEngine STIGs Compliance Example
      +## CFEngine STIGs compliance example
       
       The Security Technical Implementation Guides (STIGs) are a method for
       standardized secure installation and maintenance of computer software and
      @@ -61,7 +60,7 @@ compliance. What are the different parts of this policy example?
         Explanation of the various policy components (human readable), referencing
         STIGs requirements id (such as ```GEN000560```)
       
      -# What are the terms of this STIGs example?
      +## What are the terms of this STIGs example?
       
       This example policy is intended as a practical example of how to achieve STIGs
       compliance within the CFEngine framework. It is provided on an as-is basis, with
      diff --git a/resources/additional-topics/teamwork.markdown b/resources/additional-topics/teamwork.markdown
      index 0f028b8f3..5721ebff4 100644
      --- a/resources/additional-topics/teamwork.markdown
      +++ b/resources/additional-topics/teamwork.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: Teamwork
       published: true
       sorting: 80
      -tags: [overviews, special topics, guide]
       ---
       
      -# What is team-work?
      +## What is team-work?
       
       
       Team work is a collaboration between individuals with different skills. It is
      @@ -39,7 +38,7 @@ Team work and policy design for inter-host cooperation are closely related. Use
       promises as a tool to explain to the individuals in a team which individual is
       responsible for what role, and to what extent.
       
      -# Creative roles
      +## Creative roles
       
       
       M. Belbin, a researcher in teamwork has identified nine abilities or roles
      @@ -80,7 +79,7 @@ ourselves: how can we use the freedom to organize into specialized teams to
       maximize human creativity, while passing hard work over to machines. Solving
       this problem is what CFEngine is about.
       
      -# Delegating roles in a collaboration
      +## Delegating roles in a collaboration
       
       
       We need to delegate responsiblity to divide and conquer a problem, both when
      @@ -91,7 +90,7 @@ and coordination.
       
       Promise theory shows that coordination needs a single point of coordination to
       be the arbiter of correctness in any collaborative process: a so-called
      -`checkpoint' or `team leader', like passport control at an airport. This
      +_checkpoint_ or _team leader_, like passport control at an airport. This
       checkpoint has to examine each contribution to the team and look for conflicts.
       
       For humans, this might be a matter of communication by meeting. CFEngine, on the
      @@ -106,7 +105,7 @@ certain hosts.
       CFEngine Community Edition has roles promises, which offer a partial solution,
       but it does not address the core issue which is that collaboration in change
       requires freedom to act, not restriction. Delegation therefore requires trust.
      -CFEngine Nova/Enterprise has `hubs' which can be coordinate large numbers of
      +CFEngine Nova/Enterprise has _hubs_ which can be coordinate large numbers of
       hosts. Coordination can also be pre-arranged as policy, so that everyone has
       their own copy of the script. This is how an orchestra scales, for instance.
       
      @@ -133,7 +132,7 @@ following.
       
       A review procedure for policy-promises is a good solution if you want to
       delegate responsibility for different parts of a policy to different sources.
      -Human judgement as the `arbiter' is irreplaceable, but tools can be added to
      +Human judgement as the _arbiter_ is irreplaceable, but tools can be added to
       make conflicts easier to detect.
       
       Promise theory underlines that, if a host or computing device accepts policy
      diff --git a/resources/best-practices.markdown b/resources/best-practices.markdown
      index 80ac1df54..2e253fb6a 100644
      --- a/resources/best-practices.markdown
      +++ b/resources/best-practices.markdown
      @@ -1,16 +1,15 @@
       ---
       layout: default
      -title: Best Practices
      +title: Best practices
       sorting: 100
       published: true
      -tags: [cfengine enterprise, best practices, user interface, mission portal]
       ---
       
      -## Policy Style Guide ##
      +## Policy style guide ##
       
      -When writing CFEngine policy using our [Policy Style Guide][Policy Style Guide] helps make your policy easily understood, debuggable and maintainable.
      +When writing CFEngine policy using our [Policy style guide][Policy style guide] helps make your policy easily understood, debuggable and maintainable.
       
      -## Version Control and Configuration Policy ##
      +## Version control and configuration policy ##
       
       CFEngine users version their policies.  It's a reasonable, easy thing
       to do: you just put `/var/cfengine/masterfiles` under version control
      @@ -54,7 +53,7 @@ infrastructure.
       
       ### How to enable it ###
       
      -Follow detailed instructions in the [Policy Deployment][Policy Deployment] guide.
      +Follow detailed instructions in the [Policy deployment][Policy deployment] guide.
       
       ## Scalability ##
       
      @@ -63,7 +62,7 @@ When running CFEngine Enterprise in a large-scale IT environment with many thous
       With CFEngine 3.6, significant testing was performed to identify the issues surrounding scalability and to determine best practices in large-scale installations of CFEngine.
       
       
      -### Moving PostgreSQL to Separate Hard Drive ###
      +### Moving PostgreSQL to separate hard drive ###
       
       Moving the PostgreSQL database to another physical hard drive from the other CFEngine components can improve the stability of large-scale installations, particularly when using a solid-state drive (SSD) for hosting the PostgreSQL database.
       
      diff --git a/resources/external-resources.markdown b/resources/external-resources.markdown
      index f754b38a6..ff13e2f00 100644
      --- a/resources/external-resources.markdown
      +++ b/resources/external-resources.markdown
      @@ -3,17 +3,10 @@ layout: default
       title: External resources
       published: true
       sorting: 30
      -tags: [overviews, learning]
       ---
       
       Use the following links to learn more about CFEngine:
       
      -* [Reading][External resources#Reading]
      -* [Training][External resources#Training]
      -* [Tools][External resources#Tools]
      -* [Support and Community][External resources#Support and Community]
      -* [Contribute to CFEngine][External resources#Contribute to CFEngine]
      -
       ## Reading ##
       
       Learn by reading information brought to you by CFEngine experts:
      @@ -40,7 +33,7 @@ configuration management best practices from the CFEngine team.
       
       * [Editors with syntax support][Editors]
       
      -### Sign Up
      +### Sign up
       
       * [On-Site Training](https://cfengine.com/events) Sign up for professional training courses
       that provide a better understanding of CFEngine and how it can help improve configuration
      @@ -48,11 +41,11 @@ management in your organization.
       
       * [Contact us](http://info.cfengine.com/ContactUs.html) to get more info on training courses.
       
      -## Support and Community ##
      +## Support and community ##
       
      -### Support Desk
      +### Support desk
       
      -* [CFEngine Enterprise Support Desk][support desk] Enterprise users have access to our support desk.
      +* [CFEngine Enterprise Support desk][support desk] Enterprise users have access to our support desk.
       
       ### Forums
       
      @@ -64,13 +57,13 @@ have downloaded the free version of CFEngine 3 Enterprise.
       
       * [help-cfengine][help-cfengine] General help for all your CFEngine questions.
       
      -### Learning Resources
      +### Learning resources
       
       Sometimes the best help is already written.
       
       * Visit our [learning resources][learning center] for guides, demos, training videos, and tools.
       
      -### Social Media
      +### Social media
       
       Stay in touch. Follow us:
       
      @@ -83,7 +76,7 @@ target="_blank">LinkedIn
       
       * Facebook
       
      -* The #cfengine IRC channel on the [libera.chat](https://web.libera.chat/?channel=#cfengine) network.
      +* The #CFEngine Matrix channel (#CFEngine:matrix.org).
       
       If you want to learn more about how CFEngine can help you and your
       organization, [contact us][contact us].
      diff --git a/resources/faq.markdown b/resources/faq.markdown
      index 9aaff2c55..026b0366e 100644
      --- a/resources/faq.markdown
      +++ b/resources/faq.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: FAQ
       published: true
       sorting: 10
      -tags: [getting started, faq]
       ---
       
       This is a collection of frequently asked questions. Contributions in the form of
      diff --git a/resources/faq/bootstrap-failed.markdown b/resources/faq/bootstrap-failed.markdown
      index 897081450..df8a1b90f 100644
      --- a/resources/faq/bootstrap-failed.markdown
      +++ b/resources/faq/bootstrap-failed.markdown
      @@ -2,7 +2,6 @@
       layout: default
       title: Bootstrapping
       published: true
      -tags: [faq]
       ---
       
       Frequently asked questions around bootstrapping, the process of starting CFEngine for the first time, and connecting the agents to the correct policy server.
      @@ -140,7 +139,7 @@ See also: [`def.acl`][Masterfiles Policy Framework#acl], [`def.trustkeysfrom`][M
       
       ### `trustkeysfrom` in `body server control`
       
      -This defines networks from which a host will automatically trust hosts. If you do not use automatic trust establishment you must arrange trust separately. The [Secure Bootstrap guide][Secure Bootstrap] details a step-by-step procedure to securely bootstrap hosts.
      +This defines networks from which a host will automatically trust hosts. If you do not use automatic trust establishment you must arrange trust separately. The [Secure bootstrap guide][Secure bootstrap] details a step-by-step procedure to securely bootstrap hosts.
       
       `cf-serverd` logs verbose and notice messages relating to un-trusted clients trying to connect:
       
      diff --git a/resources/faq/debugging-slow-queries.markdown b/resources/faq/debugging-slow-queries.markdown
      index de2d822bb..603dc5da4 100644
      --- a/resources/faq/debugging-slow-queries.markdown
      +++ b/resources/faq/debugging-slow-queries.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Debugging Slow Queries
      +title: Debugging slow queries
       published: true
       sorting: 90
      -tags: [ FAQ, Enterprise, debug, Mission Portal ]
       ---
       
       If Mission Portal seems to take too much time to generate pages or reports or if API calls seem
      diff --git a/resources/faq/enterprise-license.markdown b/resources/faq/enterprise-license.markdown
      index 545ac22cb..8c4e9fb0c 100644
      --- a/resources/faq/enterprise-license.markdown
      +++ b/resources/faq/enterprise-license.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Requesting a CFEngine Enterprise License
       published: true
       sorting: 40
      -tags: [getting started, installation, enterprise production, license]
       ---
       
       To get a license please open a [support request](https://support.northern.tech)
      diff --git a/resources/faq/enterprise-report-collection.markdown b/resources/faq/enterprise-report-collection.markdown
      index e07923c84..b728b1795 100644
      --- a/resources/faq/enterprise-report-collection.markdown
      +++ b/resources/faq/enterprise-report-collection.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Enterprise report collection
       published: true
       sorting: 90
      -tags: [ FAQ, Enterprise, reporting, health, cf-hub ]
       ---
       
       Frequently asked questions on Enterprise report collection.
      @@ -113,7 +112,7 @@ $ curl -s -u admin:admin http://hub/api/query -X POST -d @agent_execution_time_i
       ]
       ```
       
      -**See also:** `Enterprise API Reference`, `Enterprise API Examples`
      +**See also:** `Enterprise API reference`, `Enterprise API examples`
       
       ## How are hosts not reporting determined?
       
      @@ -134,7 +133,7 @@ Note: It's called "blueHostHorizon" because older versions of Mission Portal
       would turn these hosts to a blue color as an indication of "hypoxia" (lack
       of oxygen, where oxygen is access to latest policy) to indicate a health issue.
       
      -**See also:** `Enterprise API Reference`, `Enterprise API Examples`, [Enterprise Settings][Settings#preferences]
      +**See also:** `Enterprise API reference`, `Enterprise API examples`, [Enterprise Settings][Settings#preferences]
       
       ## Which hosts are pending trust revocation?
       
      diff --git a/resources/faq/enterprise-report-filtering.markdown b/resources/faq/enterprise-report-filtering.markdown
      index 0a94c4f1f..9f382dedf 100644
      --- a/resources/faq/enterprise-report-filtering.markdown
      +++ b/resources/faq/enterprise-report-filtering.markdown
      @@ -3,10 +3,9 @@ layout: default
       title: Enterprise Report Filtering
       published: true
       sorting: 90
      -tags: [getting started, faq, enterprise]
       ---
       
      -## Filtering Inventoried Lists
      +## Filtering inventoried lists
       
       When filtering an inventoried list item filtering can be based on one or more
       elements of the specific inventoried item. Note that when filtering for multiple
      diff --git a/resources/faq/enterprise.markdown b/resources/faq/enterprise.markdown
      index aab4c0fc5..5b3c43667 100644
      --- a/resources/faq/enterprise.markdown
      +++ b/resources/faq/enterprise.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Enterprise Reporting database
      +title: Enterprise reporting database
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       Frequently asked questions on the Enterprise reporting database.
      @@ -26,19 +25,19 @@ The database runs under the `cfpostgres` user.
       
       ## What are the requirements for installing CFEngine Enterprise?
       
      -### General Information
      +### General information
       
      -* [Pre-Installation Checklist][Pre-Installation Checklist]
      -* [Supported Platforms and Versions][Supported Platforms and Versions]
      +* [Pre-installation checklist][Pre-installation checklist]
      +* [Supported platforms and versions][Supported platforms and versions]
       
      -### Users and Permissions
      +### Users and permissions
       
       * CFEngine Enterprise makes an attempt to create the local users `cfapache` and
         `cfpostgres`, as well as group `cfapache` during install.
       
      -## How does Enterprise Scale?
      +## How does Enterprise scale?
       
      -See best practices on [scalability][Best Practices#Scalability]
      +See best practices on [scalability][Best practices#Scalability]
       
       ## Is it normal to have many cf-hub processes running?
       
      @@ -47,7 +46,7 @@ See best practices on [scalability][Best Practices#Scalability]
       ## What steps should I take after installing CFEngine Enterprise?
       
       There are general steps to be taken outlined in
      -[Post-Installation Configuration][General Installation#Post-Installation Configuration].
      +[Post-installation configuration][General installation#Post-installation configuration].
       
       In addition to this, Enterprise uses the local mail relay, and it is assumed
       that the server where CFEngine Enterprise is installed on has proper mail setup.
      diff --git a/resources/faq/fhs.markdown b/resources/faq/fhs.markdown
      index ee275dc37..ebaf2a288 100644
      --- a/resources/faq/fhs.markdown
      +++ b/resources/faq/fhs.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Why does CFEngine install into /var/cfengine instead of following the FHS?
       published: true
       sorting: 90
      -tags: [FAQ, FHS ]
       ---
       
       The Unix Filesystem Hierarchy Standard is a specification for standardizing
      diff --git a/resources/faq/find-public-key-for-host-sha.markdown b/resources/faq/find-public-key-for-host-sha.markdown
      index fe7173c89..5ce7bb6fd 100644
      --- a/resources/faq/find-public-key-for-host-sha.markdown
      +++ b/resources/faq/find-public-key-for-host-sha.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: How do I find the public key for a given host
       published: true
       sorting: 90
      -tags: [ FAQ, cf-key  ]
       ---
       
       Trying to locate the public key for a host on your hub in order to validate
      diff --git a/resources/faq/fix-trust-after-ip-change.markdown b/resources/faq/fix-trust-after-ip-change.markdown
      index fddccc784..3a2eeba14 100644
      --- a/resources/faq/fix-trust-after-ip-change.markdown
      +++ b/resources/faq/fix-trust-after-ip-change.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: How do I fix trust after an IP change?
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       Symptom:
      diff --git a/resources/faq/fix-undefined-body-error.markdown b/resources/faq/fix-undefined-body-error.markdown
      index defd2f14b..3ead18a53 100644
      --- a/resources/faq/fix-undefined-body-error.markdown
      +++ b/resources/faq/fix-undefined-body-error.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: How do I fix undefined body errors?
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       When running policy you see `error: Undefined body`. For example:
      diff --git a/resources/faq/how-does-cfengine-work-agent-workflow.png b/resources/faq/how-does-cfengine-work-agent-workflow.png
      index 6a7f2488a..e44ccfe64 100644
      Binary files a/resources/faq/how-does-cfengine-work-agent-workflow.png and b/resources/faq/how-does-cfengine-work-agent-workflow.png differ
      diff --git a/resources/faq/how-does-cfengine-work-process.png b/resources/faq/how-does-cfengine-work-process.png
      index 68c161b2e..83023fafa 100644
      Binary files a/resources/faq/how-does-cfengine-work-process.png and b/resources/faq/how-does-cfengine-work-process.png differ
      diff --git a/resources/faq/integrate-custom-policy.markdown b/resources/faq/integrate-custom-policy.markdown
      index 3a0e31881..94d2fed32 100644
      --- a/resources/faq/integrate-custom-policy.markdown
      +++ b/resources/faq/integrate-custom-policy.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: How do I integrate custom policy?
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       There are many different ways that custom polices can be organized. CFEngine
      diff --git a/resources/faq/manual-execution.markdown b/resources/faq/manual-execution.markdown
      index 258b2b083..72776e0f8 100644
      --- a/resources/faq/manual-execution.markdown
      +++ b/resources/faq/manual-execution.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Manual Execution
      +title: Manual execution
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       Frequently asked questions on manual execution.
      @@ -103,4 +102,4 @@ This command will run `cf-agent` with the additional class `patch_and_reboot` on
       classes it is using must be resolvable during pre-evaluation as the full
       evaluation is only allowed when the classes are found to be defined.
       
      -**See also:** [How is "recently seen" determined][Components#lastseenexpireafter], [`cf-runagent`][cf-runagent], [pre-evaluation][Normal Ordering#agent pre-evaluation step]
      +**See also:** [How is "recently seen" determined][Components#lastseenexpireafter], [`cf-runagent`][cf-runagent], [pre-evaluation][Normal ordering#agent pre-evaluation step]
      diff --git a/resources/faq/mustache-templating.markdown b/resources/faq/mustache-templating.markdown
      index 53506b612..f57209ac0 100644
      --- a/resources/faq/mustache-templating.markdown
      +++ b/resources/faq/mustache-templating.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Mustache templating
       published: true
       sorting: 90
      -tags: [getting started, mustache, faq]
       ---
       
       ## CFEngine specific extensions
      @@ -43,6 +42,23 @@ Version: CFEngine {{#classes.enterprise}}Enterprise{{/classes.enterprise}} {{var
       ```
       {% endraw %}
       
      +## How do I render a section only if a given class is not defined?
      +
      +In the mustache documentation this is referred to as an *inverted section*.
      +
      +In this mustache example the word ```Enterprise``` will only be rendered if the
      +class ```cfengine_enterprise``` is defined and the word ```Community``` will
      +only be rendered if the class ```cfengine_enterprise``` is not defined.
      +
      +This template should not be passed a data container; it uses the `datastate()`
      +of the CFEngine system. That's where `classes.cfengine_enterprise` and
      +`vars.sys.cf_version` came from.
      +
      +{% raw %}
      +```
      +Version: CFEngine {{#classes.cfengine_enterprise}}Enterprise{{/classes.cfengine_enterprise}}{{^classes.cfengine_enterprise}}Community{{/classes.cfengine_enterprise}} {{vars.sys.cf_version}}
      +```
      +{% endraw %}
       
       ## How do I use class expressions?
       
      diff --git a/resources/faq/output-email.markdown b/resources/faq/output-email.markdown
      index 4278800a3..1eec8f91e 100644
      --- a/resources/faq/output-email.markdown
      +++ b/resources/faq/output-email.markdown
      @@ -3,15 +3,12 @@ layout: default
       title: Agent output email
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       ## How do I set the email where agent reports are sent?
       
      -The agent report email functionality is configured in `body executor control`
      -https://github.com/cfengine/masterfiles/blob/{{site.cfengine.branch}}/controls/cf_execd.cf.
      -It defaults to `root@$(def.domain)` which is configured in `bundle common def`
      -https://github.com/cfengine/masterfiles/blob/{{site.cfengine.branch}}/def.cf.
      +The agent report email functionality is configured in `body executor control` ([find in GitHub](https://github.com/search?q=repo%3Acfengine%2Fmasterfiles+mail+path%3A**%2Fcf_execd.cf&type=code)).
      +It defaults to `root@$(def.domain)` which is configured in `bundle common def` ([find in GitHub](https://github.com/search?q=repo%3Acfengine%2Fmasterfiles+%22mailto%22+path%3A**%2Fdef.cf&type=code)).
       
       **See also:** [`def.mailto`][Masterfiles Policy Framework#mailto].
       
      diff --git a/resources/faq/show-classes-and-vars.markdown b/resources/faq/show-classes-and-vars.markdown
      index 2a38a5788..c1a623d9d 100644
      --- a/resources/faq/show-classes-and-vars.markdown
      +++ b/resources/faq/show-classes-and-vars.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: How can I tell what Classes and Variables are defined?
      +title: How can I tell what classes and variables are defined?
       published: true
       sorting: 90
      -tags: [getting started, installation, faq]
       ---
       
       You can see a high level overview of the first order classes and variables using
      diff --git a/resources/faq/tuning-postgresql.markdown b/resources/faq/tuning-postgresql.markdown
      index 9fc1213e9..bc971f54b 100644
      --- a/resources/faq/tuning-postgresql.markdown
      +++ b/resources/faq/tuning-postgresql.markdown
      @@ -2,7 +2,6 @@
       layout: default
       title: Tuning PostgreSQL
       published: true
      -tags: [ FAQ, Enterprise, Mission Portal, PostgreSQL ]
       ---
       
       During install the CFEngine Enterprise Hub Package pre-configures PostgreSQL with a configuration for low (<3GB), medium (>3GB <64GB) or high (>64GB) memory which adjusts the values of `effective_cache_size`, `shared_buffers`, and `maintenance_work_mem`.
      @@ -37,7 +36,7 @@ Parameters commonly tuned:
       
       Tuning tools like [pgtune](https://github.com/kofemann/pgtune) and [pgconfigurator](https://www.cybertec-postgresql.com/en/products/pgconfigurator/) can be helpful in adjusting your settings.
       
      -**See Also:**
      +**See also:**
       
       - [Debugging slow queries][debugging slow queries].
      -- [Policy server requirements][Installing enterprise for production#Policy Server Requirements].
      +- [Policy server requirements][Installing enterprise for production#Policy server requirements].
      diff --git a/resources/faq/unable-to-log-in-mission-portal.markdown b/resources/faq/unable-to-log-in-mission-portal.markdown
      index 8b018e08c..1f92fe489 100644
      --- a/resources/faq/unable-to-log-in-mission-portal.markdown
      +++ b/resources/faq/unable-to-log-in-mission-portal.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Unable to log into Mission Portal
       published: true
       sorting: 90
      -tags: [getting started, installation, faq, Mission Portal]
       ---
       
       ## Mismatched names in SSL certificate
      diff --git a/resources/faq/uninstall-reinstall.markdown b/resources/faq/uninstall-reinstall.markdown
      index 5c946cf93..b572a034d 100644
      --- a/resources/faq/uninstall-reinstall.markdown
      +++ b/resources/faq/uninstall-reinstall.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Uninstalling/Reinstalling
      +title: Uninstalling / reinstalling
       published: true
       sorting: 40
      -tags: [uninstall, reinstall]
       ---
       
       ## What is left behind after uninstalling?
      diff --git a/resources/faq/users.markdown b/resources/faq/users.markdown
      index ea6e0d01d..cdc6feff7 100644
      --- a/resources/faq/users.markdown
      +++ b/resources/faq/users.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Users
       published: true
       sorting: 90
      -tags: [getting started, installation, enterprise, faq]
       ---
       
       Frequently asked questions about managing users from policy.
      diff --git a/resources/faq/variables.markdown b/resources/faq/variables.markdown
      index f451ae56c..00f7853ed 100644
      --- a/resources/faq/variables.markdown
      +++ b/resources/faq/variables.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: How do I pass a data type variable?
       published: true
       sorting: 90
      -tags: [getting started, vars, faq]
       ---
       
       Data type variables also known as "data containers" are passed using the same
      diff --git a/resources/faq/what-did-cfengine-change.markdown b/resources/faq/what-did-cfengine-change.markdown
      index b811b4ce8..0dd0d81e4 100644
      --- a/resources/faq/what-did-cfengine-change.markdown
      +++ b/resources/faq/what-did-cfengine-change.markdown
      @@ -2,7 +2,6 @@
       layout: default
       title: What did CFEngine do?
       published: true
      -tags: [getting started, faq, logging, reporting ]
       ---
       
       This page presents a few ways of understanding what CFEngine has done to your machine.
      @@ -32,19 +31,20 @@ bundle edit_line lines_present(lines)
       # @brief Ensure `lines` are present in the file. Lines that do not exist are appended to the file
       # @param List or string that should be present in the file
       #
      -# **Example:**
      +# Example:
       #
      -# ```cf3
      -# bundle agent example
      -# {
      -#  vars:
      -#    "nameservers" slist => { "8.8.8.8", "8.8.4.4" };
      +#     bundle agent example
      +#     {
      +#      vars:
      +#        "nameservers"
      +#          slist => { "8.8.8.8", "8.8.4.4" };
       #
      -#  files:
      -#      "/etc/resolv.conf" edit_line => lines_present( @(nameservers) );
      -#      "/etc/ssh/sshd_config" edit_line => lines_present( "PermitRootLogin no" );
      -# }
      -# ```
      +#      files:
      +#        "/etc/resolv.conf"
      +#          edit_line => lines_present( @(nameservers) );
      +#        "/etc/ssh/sshd_config"
      +#          edit_line => lines_present( "PermitRootLogin no" );
      +#     }
       {
         insert_lines:
       
      @@ -135,7 +135,7 @@ verbose: Outcome of version (not specified) (agent-0): Promises observed - Total
       
       ### Promise logging
       
      -Promises can be configured to [log their outcomes][Promise Types#log_repaired]
      +Promises can be configured to [log their outcomes][Promise types#log_repaired]
       to a file with `log_kept`, `log_repaired`, and `log_failed` attributes in an action body.
       
       ```cf3
      @@ -236,7 +236,7 @@ Example response:
       }
       ```
       
      -See Also: [query rest api][Tracking changes]
      +See also: [query rest api][Tracking changes]
       
       ### Custom Reports and Query API
       
      @@ -261,7 +261,7 @@ GROUP BY namespace, bundlename, promisetype,promisehandle,promiser
       ORDER BY count DESC
       ```
       
      -Reference: [query api examples][SQL Query Examples]
      +Reference: [query api examples][SQL query examples]
       
       ### promise_log.jsonl
       
      diff --git a/resources/faq/what-is-promise-locking.markdown b/resources/faq/what-is-promise-locking.markdown
      index a3821716a..5dd2fe289 100644
      --- a/resources/faq/what-is-promise-locking.markdown
      +++ b/resources/faq/what-is-promise-locking.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: What is promise locking?
       published: true
       sorting: 90
      -tags: [getting started, faq, locking]
       ---
       
       By default when the agent runs each promise that has an outcome
      diff --git a/resources/faq/why-are-files-not-being-distributed.markdown b/resources/faq/why-are-files-not-being-distributed.markdown
      index 2cf51a308..9b084f103 100644
      --- a/resources/faq/why-are-files-not-being-distributed.markdown
      +++ b/resources/faq/why-are-files-not-being-distributed.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Why are some files inside masterfiles not being updated/distributed?
       published: true
       sorting: 90
      -tags: [getting started, installation, faq ]
       ---
       
       During agent bootstrap all files found in `masterfiles` are copied to
      diff --git a/resources/faq/why-are-remote-agents-not-updating.markdown b/resources/faq/why-are-remote-agents-not-updating.markdown
      index f35c1e1c0..74cb7b7b5 100644
      --- a/resources/faq/why-are-remote-agents-not-updating.markdown
      +++ b/resources/faq/why-are-remote-agents-not-updating.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Why are remote agents not updating?
       published: true
       sorting: 90
      -tags: [getting started, installation, faq, cf_promises_validated ]
       ---
       
       The [masterfiles policy framework][Masterfiles Policy Framework] defaults to using
      diff --git a/resources/faq/why-knowledge-management.markdown b/resources/faq/why-knowledge-management.markdown
      index 6f450e8e1..e8e527c7e 100644
      --- a/resources/faq/why-knowledge-management.markdown
      +++ b/resources/faq/why-knowledge-management.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Why knowledge management?
       published: true
       sorting: 3
      -tags: [getting started, faq]
       ---
       
       
      diff --git a/web-ui.markdown b/web-ui.markdown
      index c3f7b0f41..a01e0d422 100644
      --- a/web-ui.markdown
      +++ b/web-ui.markdown
      @@ -3,18 +3,17 @@ layout: default
       title: Web UI
       published: true
       sorting: 40
      -tags: ["Enterprise Edition"]
       ---
       
       The challenge in engineering IT infrastructure, especially as it scales
       vertically and horizontally, is to recognize the system components, what they do
       at any given moment in time (or over time), and when and how they change state.
       
      -CFEngine Enterprise's data collection service, the `cf-hub` collector, collects,
      +CFEngine Enterprise's data collection service, `cf-hub`, collects,
       organizes, and stores data from every host. The data is stored primarily in a
       PostgreSQL database.
       
      -CFEngine Enterprise's user interface, the Mission Portal makes that data
      +CFEngine Enterprise's user interface, Mission Portal, makes that data
       available to authorized users as high level reports or alerts and notifications.
       The reports can be designed in a GUI report builder or directly with SQL
       statements passed to PostgreSQL.
      @@ -28,18 +27,18 @@ The dashboard contains informative widgets that you can customize to create
       alerts. All notifications of alert state changes, e.g. from OK to not-OK, are
       stored in an event log for later inspection and analysis.
       
      -### Make changes to shared dashboard
      +### Make changes to a shared dashboard
       
       Clone dashboard possibility
       
      -Create an editable copy by clicking the button that appears when you hover over
      +Create an editable copy by clicking the edit button (pencil icon) that appears when you hover over
       the dashboard's row.
       
       ### Alert widgets
       
       Enterprise UI Alerts
       
      -Alerts can have three different severity level: low, medium and high. These are
      +Alerts can have three different severity levels: low, medium and high. These are
       represented by yellow, orange and red rings respectively, along with the
       percentage of hosts alerts have triggered on. Hovering over the widget will show
       the information as text in a convenient list format.
      @@ -54,7 +53,7 @@ underlying issue to avoid unnecessary triggering and notifications.
       Alerts can have three different states: OK, triggered, and paused. It is easy to
       filter by state on each widget's alert overview.
       
      -Find out more: [Alerts and Notifications][]
      +Find out more: [Alerts and notifications][]
       
       ### Changes widget
       
      @@ -93,16 +92,15 @@ All Events can be searched and viewed from the Event Log page.
       Mission Portal - Events View whole system events RBAC page
       
       
      -### Host count widget
      +### Newly bootstrapped hosts widget
       
      -The hosts count widget helps to visualize the number of hosts bootstrapped to CFEngine over time.
      +The Newly bootstrapped hosts widget helps to visualize the number of hosts bootstrapped to CFEngine over time.
       
      -Dashboard Host count
      +Dashboard Newly bootstrapped
       
       ## Hosts
       
      -CFEngine collects data on promise compliance, and sorts hosts according to 3
      -different categories: erroneous, fully compliant, and lacking data.
      +CFEngine collects data on promise compliance, and sorts hosts into two categories: 100% compliant, and not.
       
       Find out more: [Hosts][]
       
      @@ -119,8 +117,6 @@ attributes are also extensible, by tagging any CFEngine variable or class, such
       as the role of the host, inside your CFEngine policy. These custom attributes
       will be automatically added to the Mission Portal.
       
      -![Enterprise UI Reporting](inventory-hover.png)
      -
       You can reduce the amount of data or find specific information by filtering on
       attributes and host groups. Filtering is independent from the data presented in
       the results table: you can filter on attributes without them being presented in
      @@ -136,7 +132,7 @@ regularly.
       
       Find out more: [Reporting][Reporting UI]
       
      -Follow along in the [custom inventory tutorial][Custom Inventory] or read the
      +Follow along in the [custom inventory tutorial][Custom inventory] or read the
       [MPF policy that provides inventory][inventory/].
       
       ## Sharing
      diff --git a/web-ui/Authentication-settings.png b/web-ui/Authentication-settings.png
      index af8bf0c63..82dd4b1d5 100644
      Binary files a/web-ui/Authentication-settings.png and b/web-ui/Authentication-settings.png differ
      diff --git a/web-ui/Mission-portal-health-dignostics-header.png b/web-ui/Mission-portal-health-dignostics-header.png
      index 1f50ad598..958c1c0e0 100644
      Binary files a/web-ui/Mission-portal-health-dignostics-header.png and b/web-ui/Mission-portal-health-dignostics-header.png differ
      diff --git a/web-ui/alerts-and-notifications.markdown b/web-ui/alerts-and-notifications.markdown
      index 3635a4d46..992dfb45d 100644
      --- a/web-ui/alerts-and-notifications.markdown
      +++ b/web-ui/alerts-and-notifications.markdown
      @@ -1,12 +1,11 @@
       ---
       layout: default
      -title: Alerts and Notifications
      +title: Alerts and notifications
       sorting: 40
       published: true
      -tags: [cfengine enterprise, user interface, mission portal]
       ---
       
      -## Create a New Alert ##
      +## Create a new alert ##
       
       * From the Dashboard, locate the rectangle with the dotted border.
       
      @@ -23,9 +22,9 @@ tags: [cfengine enterprise, user interface, mission portal]
       * Add a unique name for the alert.
       
       * Each alert has a visual indication of its severity, represented by one of the following colors:
      -	* **Low**: Yellow
      -	* **Medium**: Orange
      -	* **High**: Red
      +  * **Low**: Yellow
      +  * **Medium**: Orange
      +  * **High**: Red
       
       
       New Alerts Severity
      @@ -45,13 +44,13 @@ tags: [cfengine enterprise, user interface, mission portal]
       New Alerts Condition Type
       
       * Each alert also has a **Condition type**:
      -	* **Policy** conditions trigger alerts based on CFEngine policy compliance status. They can be set on bundles, promisees, and promises. If nothing is specified, they will trigger alerts for all policy.
      +  * **Policy** conditions trigger alerts based on CFEngine policy compliance status. They can be set on bundles, promisees, and promises. If nothing is specified, they will trigger alerts for all policy.
       
      -	* **Inventory** conditions trigger alerts for inventory attributes. These attributes correspond to the ones found in inventory reports.
      +  * **Inventory** conditions trigger alerts for inventory attributes. These attributes correspond to the ones found in inventory reports.
       
      -	* **Software Updates** conditions trigger alerts based on packages available for update in the repository. They can be set either for a specific version or trigger on the latest version available. If neither a package nor a version is specified, they will trigger alerts for any update.
      +  * **Software Updates** conditions trigger alerts based on packages available for update in the repository. They can be set either for a specific version or trigger on the latest version available. If neither a package nor a version is specified, they will trigger alerts for any update.
       
      -	* **Custom SQL** conditions trigger alerts based on an SQL query. The SQL query must returns at least one column - `hostkey`.
      +  * **Custom SQL** conditions trigger alerts based on an SQL query. The SQL query must returns at least one column - `hostkey`.
       
       * Alert conditions can be limited to a subset of hosts.
       
      diff --git a/web-ui/clone-dashboard.png b/web-ui/clone-dashboard.png
      index 041b127cc..5731d1a7e 100644
      Binary files a/web-ui/clone-dashboard.png and b/web-ui/clone-dashboard.png differ
      diff --git a/web-ui/custom-actions-for-alerts.markdown b/web-ui/custom-actions-for-alerts.markdown
      index d4c44724e..b69139a20 100644
      --- a/web-ui/custom-actions-for-alerts.markdown
      +++ b/web-ui/custom-actions-for-alerts.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Custom actions for Alerts
      +title: Custom actions for alerts
       sorting: 50
       published: true
      -tags: [cfengine enterprise, user interface, mission portal]
       ---
       
       Once you have become familiar with the [Alerts widgets][Web UI#Alert widgets], you might see the need to integrate the alerts with an existing system like Nagios, instead of relying on emails for getting notified.
      @@ -95,7 +94,9 @@ Given an alert that triggers on a policy bundle being not kept (failed), the fol
       Saving this as a file, e.g. 'alert_parameters_test', can be useful while writing and testing your Custom action script.
       You could then simply test your Custom action script, e.g. 'cfengine_custom_action_ticketing.py', by running
       
      -    ./cfengine_custom_action_ticketing alert_parameters_test
      +```command
      +./cfengine_custom_action_ticketing alert_parameters_test
      +```
       
       When you get this to work as expected on the commmand line, you are ready to upload the script to the Mission Portal, as outlined below.
       
      @@ -104,18 +105,21 @@ When you get this to work as expected on the commmand line, you are ready to upl
       
       The following Custom action script will log the status and definition of a policy alert to syslog.
       
      -    #!/bin/bash
      +```bash
      +[file=cfengine_custom_notification_policy_syslog.sh]
      +#!/bin/bash
       
      -    source $1
      +source $1
       
      -    if [ "$ALERT_CONDITION_TYPE" != "policy" ]; then
      -       logger -i "error: CFEngine Custom action script $0 triggered by non-policy alert type"
      -       exit 1
      -    fi
      +if [ "$ALERT_CONDITION_TYPE" != "policy" ]; then
      +   logger -i "error: CFEngine Custom action script $0 triggered by non-policy alert type"
      +   exit 1
      +fi
       
      -    logger -i "Policy alert '$ALERT_NAME' $ALERT_STATUS. Now triggered on $ALERT_FAILED_HOST hosts. Defined with $ALERT_POLICY_CONDITION_FILTERBY='$ALERT_POLICY_CONDITION_FILTERITEMNAME', promise handle '$ALERT_POLICY_CONDITION_PROMISEHANDLE' and outcome $ALERT_POLICY_CONDITION_PROMISEOUTCOME"
      +logger -i "Policy alert '$ALERT_NAME' $ALERT_STATUS. Now triggered on $ALERT_FAILED_HOST hosts. Defined with $ALERT_POLICY_CONDITION_FILTERBY='$ALERT_POLICY_CONDITION_FILTERITEMNAME', promise handle '$ALERT_POLICY_CONDITION_PROMISEHANDLE' and outcome $ALERT_POLICY_CONDITION_PROMISEOUTCOME"
       
      -    exit $?
      +exit $?
      +```
       
       What gets logged to syslog depends on which alert is associated with the script, but an example log-line is as follows:
       
      diff --git a/web-ui/dashboard-widget-hosts-count.png b/web-ui/dashboard-widget-hosts-count.png
      deleted file mode 100644
      index ac9985dbd..000000000
      Binary files a/web-ui/dashboard-widget-hosts-count.png and /dev/null differ
      diff --git a/web-ui/dashboard-widget-newly-bootstrapped.png b/web-ui/dashboard-widget-newly-bootstrapped.png
      new file mode 100644
      index 000000000..b3bbeef8b
      Binary files /dev/null and b/web-ui/dashboard-widget-newly-bootstrapped.png differ
      diff --git a/web-ui/debugging-mission-portal.markdown b/web-ui/debugging-mission-portal.markdown
      index 153d3ab7a..7145b71f8 100644
      --- a/web-ui/debugging-mission-portal.markdown
      +++ b/web-ui/debugging-mission-portal.markdown
      @@ -3,20 +3,20 @@ layout: default
       title: Debugging Mission Portal
       published: true
       sorting: 90
      -tags: [ FAQ, Enterprise, debug, Mission Portal ]
       ---
       
       1.  Set the API log level to DEBUG in Mission Portal settings.
       
       2.  Edit `/var/cfengine/share/GUI/index.php` and set `ENVIRONMENT` to `development`
       
      -    ```
      +    ```php
      +    [file=/var/cfengine/share/GUI/index.php]
           define('ENVIRONMENT', 'development');
           ```
       
       3.  Run the hubs policy.
       
      -    ```sh
      +    ```command
           cf-agent -KI
           ```
       
      @@ -24,20 +24,19 @@ tags: [ FAQ, Enterprise, debug, Mission Portal ]
       
           For systemd manged systems (RedHat/Centos7, Debian 7+, Ubuntu 15.04+):
       
      -    ```sh
      +    ```command
           systemctl restart cf-apache
           ```
       
           For sysv init managed systems:
       
      -    ```sh
      -    pkill httpd
      -    cf-agent -KI
      +    ```command
      +    pkill httpd && cf-agent -KI
           ```
       
           or
       
      -    ```sh
      +    ```command
           LD_LIBRARY_PATH=/var/cfengine/lib:$LD_LIBRARY_PATH /var/cfengine/httpd/bin/apachectl restart
           ```
       
      diff --git a/web-ui/enterprise-reporting.markdown b/web-ui/enterprise-reporting.markdown
      index 632e53b9e..aa547b674 100644
      --- a/web-ui/enterprise-reporting.markdown
      +++ b/web-ui/enterprise-reporting.markdown
      @@ -1,16 +1,15 @@
       ---
       layout: default
      -title: Enterprise Reporting
      +title: Enterprise reporting
       sorting: 50
       published: true
      -tags: [cfengine enterprise, user interface, mission portal]
       ---
       
       CFEngine Enterprise can report on promise outcomes (changes made by `cf-agent`
       across your infrastructure), variables, classes, and measurements taken by
       `cf-monitord`. Reports cover fine grained policy details, explore all the
       options by checking out the [custom reports section][Reporting UI#query builder]
      -of the Enterprise Reporting module.
      +of the Enterprise reporting module.
       
       Specifically which information allowed to be collected by the hub for reporting
       is configured by [`report_data_select` bodies][access#report_data_select].
      @@ -39,7 +38,7 @@ Framework). The MPF includes ```inventory``` and ```report``` in
       
       If it's desirable for the classes and variables to be available in specialized
       inventory subsystem then it should be tagged with `inventory` and given an
      -additional `attribute_name=` tag as described in the [custom inventory example][Custom Inventory].
      +additional `attribute_name=` tag as described in the [custom inventory example][Custom inventory].
       
       ```cf-hub``` collects information resulting from all other promise types (except
       `reports`, and `defaults` which cf-hub does not collect for). This can be
      diff --git a/web-ui/enterprise-reporting/client-initiated-reporting.markdown b/web-ui/enterprise-reporting/client-initiated-reporting.markdown
      index e80ffbd9f..a9659a67e 100644
      --- a/web-ui/enterprise-reporting/client-initiated-reporting.markdown
      +++ b/web-ui/enterprise-reporting/client-initiated-reporting.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Client Initiated Reporting / Call collect
      +title: Client initiated reporting / call collect
       sorting: 60
       published: true
      -tags: [cfengine enterprise, reporting, call collect]
       ---
       
       Pull collect is the default mode of reporting.
      @@ -20,7 +19,8 @@ Call collect and Client Initiated Reporting are the same, they both refer to the
       
       The easiest way to enable call collect is via augments files, modify `/var/cfengine/masterfiles/def.json` on the hub:
       
      -```
      +```json
      +[file=def.json]
       {
         "classes": {
           "client_initiated_reporting_enabled": [ "any" ]
      @@ -53,7 +53,7 @@ Neither the call collect thread nor the worker thread pool are affected by the h
       
       This is recorded in the PostgreSQL database on the hub, and can be queried from command line:
       
      -```
      +```command
       /var/cfengine/bin/psql -d cfdb -c "SELECT * FROM __hosts WHERE iscallcollected='t'";
       ```
       
      diff --git a/web-ui/enterprise-reporting/reporting-architecture.markdown b/web-ui/enterprise-reporting/reporting-architecture.markdown
      index 913c45d78..3d13117ae 100644
      --- a/web-ui/enterprise-reporting/reporting-architecture.markdown
      +++ b/web-ui/enterprise-reporting/reporting-architecture.markdown
      @@ -1,9 +1,8 @@
       ---
       layout: default
      -title: Reporting Architecture
      +title: Reporting architecture
       published: true
       sorting: 10
      -tags: [manuals, enterprise, reporting, architecture, cf-hub]
       ---
       
       The reporting architecture of CFEngine Enterprise uses two software
      @@ -21,7 +20,9 @@ each host to download new data.
       
       To collect reports from any host manually, run the following:
       
      -    $ /var/cfengine/bin/cf-hub -H 
      +```command
      +/var/cfengine/bin/cf-hub -H 
      +```
       
       * Add `-v` to run in verbose mode to diagnose connectivity issues and trace the data collected.
       
      diff --git a/web-ui/enterprise-reporting/reporting_ui.markdown b/web-ui/enterprise-reporting/reporting_ui.markdown
      index f8919ff76..40f50bbbe 100644
      --- a/web-ui/enterprise-reporting/reporting_ui.markdown
      +++ b/web-ui/enterprise-reporting/reporting_ui.markdown
      @@ -3,12 +3,11 @@ layout: default
       title: Reporting UI
       sorting: 50
       published: true
      -tags: [cfengine enterprise, user interface, mission portal]
       ---
       
      -CFEngine collects a large amount of data. To inspect it, you can run and schedule pre-defined reports or use the [query builder][Reporting UI#Query Builder] for your own custom reports. You can save these queries for later use, and schedule reports for specified times.
      +CFEngine collects a large amount of data. To inspect it, you can run and schedule pre-defined reports or use the [query builder][Reporting UI#Query builder] for your own custom reports. You can save these queries for later use, and schedule reports for specified times.
       
      -If you are familiar with SQL syntax, you can input your query into the interface directly. Make sure to take a look at the database schema. Please note: manual entries in the query field at the bottom of the [query builder][Reporting UI#Query Builder] will invalidate all field selections and filters above, and vice-versa.
      +If you are familiar with SQL syntax, you can input your query into the interface directly. Make sure to take a look at the database schema. Please note: manual entries in the query field at the bottom of the [query builder][Reporting UI#Query builder] will invalidate all field selections and filters above, and vice-versa.
       
       You can share the report with other users - either by using "Save" button, or by base64-encoding the report query into a URL. You can also provide an optional title by adding `title` parameter to the URL, like this:
       
      @@ -31,12 +30,12 @@ You can also filter on the type of promise: user defined, system defined, or all
       
       See also:
       
      -* [Reporting Architecture][Reporting Architecture]
      -* [SQL Queries Using the Enterprise API][SQL Queries Using the Enterprise API]
      +* [Reporting architecture][Reporting architecture]
      +* [SQL queries using the Enterprise API][SQL queries using the Enterprise API]
       
      -## Query Builder ##
      +## Query builder ##
       
      -Users not familiar with SQL syntax can easily create their own custom reports in this interface. Please note that query builder can be [extended with your custom data][Extending Query Builder in Mission portal#How to add new table to Query builder].
      +Users not familiar with SQL syntax can easily create their own custom reports in this interface. Please note that query builder can be [extended with your custom data][Extending Query builder in Mission portal#How to add new table to query builder].
       
       * Tables - Select the data tables you want include in your report first.
           * When more than one table is selected the Query builder opens modal window to select the ([join strategy  between tables](https://www.postgresql.org/docs/current/tutorial-join.html)):
      @@ -60,17 +59,18 @@ the following defines the attribute `Role` which is set to
       `database_server`. You need to add it to the top-level
       `bundlesequence` in `promises.cf` or in a bundle that it calls.
       
      -	```cf3
      -	bundle agent myreport
      -	{
      -	  vars:
      -		  "myrole"
      -		  string => "database_server",
      -		  meta => { "inventory", "attribute_name=Role" };
      -	}
      -	```
      +```cf3
      +[file=promises.cf]
      +bundle agent myreport
      +{
      +  vars:
      +    "myrole"
      +      string => "database_server",
      +      meta => { "inventory", "attribute_name=Role" };
      +}
      +```
       
      -* note the [`meta`][Promise Types#meta] tag `inventory`
      +* note the [`meta`][Promise types#meta] tag `inventory`
       
       * The hub must be able to collect the reports from the client. TCP
       port 5308 must be open and, because 3.6 uses TLS, should not be
      @@ -97,7 +97,7 @@ large number of clinets that have not been collected from that become available
       at once can cause increased load on the hub collector and affect its
       performance until it has been able to collect from all hosts.
       
      -## Define a New Single Table Report ##
      +## Define a new single table report ##
       
       1. In *Mission Portal* select the *Report* application icon on the left hand side of the screen.
       2. This will bring you to the *Report builder* screen.
      @@ -110,7 +110,7 @@ performance until it has been able to collect from all hosts.
       9. Leave *Filters*, *Sort*, and *Limit* at the default settings.
       10. Click the orange *Run* button in the bottom right hand corner.
       
      -## Check Report Results ##
      +## Check report results ##
       
       1. The report generated will show each of the selected columns across the report table's header row.
       2. In this tutorial the columns being reported back should be: *Host key*, *Last report time*, *Host name*, *IP address*, *First report-time*.
      @@ -125,26 +125,26 @@ performance until it has been able to collect from all hosts.
       11. Click *OK* to download or email the *csv* or *pdf* version of the report.
       12. Once the report is generated it will be available for download or will be emailed.
       
      -## Inventory Management ##
      +## Inventory management ##
       
       Inventory allows you to define the set of hosts to report on.
       
       The main Inventory screen shows the current set of hosts, together with relevant information such as operating system type, kernel and memory size.
       
      -Inventory Management
      +Inventory management
       
       To begin filtering, one would first select the *Filters* drop down, and then select an attribute to filter on (e.g. OS type = linux)
       
      -Inventory Management
      +Inventory management
       
       After applying the filter, it may be convenient to add the attribute as one of the table columns.
       
      -Inventory Management
      +Inventory management
       
       Changing the filter, or adding additional attributes for filtering, is just as easy.
       
      -Inventory Management
      +Inventory management
       
       We can see here that there are no Windows machines bootstrapped to this hub.
       
      -Inventory Management
      +Inventory management
      diff --git a/web-ui/enterprise-reporting/sql-queries-enterprise-api.markdown b/web-ui/enterprise-reporting/sql-queries-enterprise-api.markdown
      index 20f973c09..b14287bcf 100644
      --- a/web-ui/enterprise-reporting/sql-queries-enterprise-api.markdown
      +++ b/web-ui/enterprise-reporting/sql-queries-enterprise-api.markdown
      @@ -1,15 +1,14 @@
       ---
       layout: default
      -title: SQL Queries Using the Enterprise API
      +title: SQL queries using the Enterprise API
       published: true
       sorting: 20
      -tags: [manuals, enterprise, reporting]
       ---
       
       The CFEngine Enterprise Hub collects information about the
       environment in a centralized database. Data is collected every 5
       minutes from all bootstrapped hosts. This data can be accessed through
      -the Enterprise Reporting API.
      +the Enterprise reporting API.
       
       Through the API, you can run CFEngine Enterprise reports with SQL
       queries. The API can create the following report queries:
      @@ -21,7 +20,7 @@ queries. The API can create the following report queries:
       -   Subscribed query: Specify a query to be run on a schedule
           and have the result emailed to someone.
       
      -### Synchronous Queries ###
      +### Synchronous queries ###
       
       Issuing a synchronous query is the most straightforward way of running
       an SQL query. We simply issue the query and wait for a result to come
      @@ -59,7 +58,7 @@ back.
             ]
           }
       
      -## Asynchronous Queries
      +## Asynchronous queries
       
       Because some queries can take some time to compute, you can
       fire off a query and check the status of it later. This is useful for
      diff --git a/web-ui/federated-reporting.markdown b/web-ui/federated-reporting.markdown
      index 5c625f3e2..35bd540ba 100644
      --- a/web-ui/federated-reporting.markdown
      +++ b/web-ui/federated-reporting.markdown
      @@ -1,17 +1,16 @@
       ---
       layout: default
      -title: Federated Reporting
      +title: Federated reporting
       published: true
       sorting: 60
      -tags: [enterprise, guide, federated reporting]
       ---
       
       ## Overview ##
       
      -Federated Reporting enables the collection of data from multiple Hubs to provide
      +Federated reporting enables the collection of data from multiple Hubs to provide
       a view in Mission Portal which can scale up beyond the capabilities of a Hub
       which manages hosts. CFEngine supports a large number of hosts per hub, around
      -5,000 hosts per hub depending on many factors. With Federated Reporting it is
      +5,000 hosts per hub depending on many factors. With Federated reporting it is
       possible to scale up to 100,000 hosts or more for the purposes of analysis and
       reporting.
       
      @@ -24,29 +23,18 @@ configure and connect the Superhub and Feeder hubs. For Feeder hubs with an
       earlier version than 3.14.0 some manual steps must be taken. Links to these
       are provided at each stage of installation and setup that follows.
       
      -* [Requirements][Federated Reporting#Requirements]
      -* [Installation][Federated Reporting#Installation]
      -* [Setup][Federated Reporting#Setup]
      -* [Operation][Federated Reporting#Operation]
      -* [Duplicate Host Management][Federated Reporting#Duplicate Host Management]
      -* [Troubleshooting][Federated Reporting#Troubleshooting]
      -* [API Setup][Federated Reporting#API Setup]
      -* [Disable Feeder][Federated Reporting#Disable Feeder]
      -* [Uninstall][Federated Reporting#Uninstall]
      -* [Superhub Upgrade][Federated Reporting#Superhub Upgrade]
      -
       ## Requirements ##
       
      -### Topology Requirements ###
      +### Topology requirements ###
       
       At this time it is not possible to bootstrap agents to the Superhub. The Superhub
       itself will be present but the behavior of other agents bootstrapped to the Superhub
       is untested and unsupported.
       
      -### Software Requirements ###
      +### Software requirements ###
       
       If your hub will have SELinux enabled, the `semanage` command must be installed.
      -This allows Federated Reporting policy to manage the trust between the superhub and
      +This allows Federated reporting policy to manage the trust between the superhub and
       feeder hubs.
       
       Add the `cfengine_mp_fr_dependencies_auto_install` to your augments file to allow
      @@ -62,7 +50,7 @@ federation policy to ensure that `semanage` is installed.
       
       See `cfengine_enterprise_federation:semanage_installed` in [cfe_internal/enterprise/federation/federation.cf][cfe_internal/enterprise/federation/federation.cf] for details on which packages are used for various distributions.
       
      -### Hardware Requirements ###
      +### Hardware requirements ###
       
       The Superhub aggregates all the data from all the Feeders connected to it which
       is a periodically running resource intensive task. The key factors contributing
      @@ -74,7 +62,7 @@ to HW requirements for the Superhub are:
       * The amount of data gathered on the Feeders from the reports sent by the
         hosts bootstrapped to them.
       
      -The current implementation of Federated Reporting is not aggregating monitoring
      +The current implementation of Federated reporting is not aggregating monitoring
       data on the Superhub which saves a lot of network traffic, processing power and
       disk space on the Superhub.
       
      @@ -105,7 +93,7 @@ and 5000 hosts per connected Feeder is:
         * 135 KiB of network data transfer per host per one pull of the data from
           Feeders.
       
      -The Federated Reporting process is logging information to the system log and so
      +The Federated reporting process is logging information to the system log and so
       timestamps from the log messages can be used to determine how long each round of
       the pull-import process has taken. If it is close to the configured refresh
       interval, the interval needs to be made longer or the hardware configuration of
      @@ -118,25 +106,25 @@ connecting more Feeders.
       
       ## Installation ##
       
      -The [General Installation][General Installation] instructions should be used to
      +The [General installation][General installation] instructions should be used to
       install CFEngine Hub on a Superhub as well as Feeder hubs.
       
       ## Setup ##
       
      -### Enable Hub management app ###
      +### Enable hub management app ###
       
       Enable Hub Management
       
       On the Superhub and all Feeders enable the Hub management
      -app by [Opening Settings][Settings#opening settings] then
      -selecting [Manage Apps][Settings#manage apps] and finally
      +app by [Opening settings][Settings#opening settings] then
      +selecting [Manage apps][Settings#manage apps] and finally
       by clicking the `On` radio button for Hub management in the Status column.
       
       Note: for pre 3.14 feeders this step is not performed.
       
      -### Enable Federated Reporting ###
      +### Enable federated reporting ###
       
      -Enable Federated Reporting
      +Enable federated reporting
       
       The Hub management app should now appear in the bottom left corner of mission
       portal.
      @@ -146,16 +134,16 @@ cause some configuration to be written in the filesystem and on next agent run
       policy will make the needed changes. You can speed up this process by running
       the agent manually.
       
      -Note: for pre 3.14 feeders, you must [Enable feeder without API][Federated Reporting#Enable feeder without API].
      +Note: for pre 3.14 feeders, you must [Enable feeder without API][Federated reporting#Enable feeder without API].
       
      -### Connect Feeder Hubs ###
      +### Connect feeder hubs ###
       
      -Connect Feeder Hubs
      +Connect feeder hubs
       
      -Refresh the Hub management on each hub to see that Federated Reporting is
      +Refresh the Hub management on each hub to see that Federated reporting is
       enabled.
       
      -After all hubs have Federated Reporting enabled visit Hub management on the
      +After all hubs have Federated reporting enabled visit Hub management on the
       Superhub to connect the Feeder hubs.
       
       On the Superhub, click on the Connect hub button to show the Connect a hub dialog.
      @@ -180,7 +168,7 @@ each Feeder every 20 minutes as well.
       You can test import immediately by running the agent on the feeders and then
       the superhub.
       
      -## Duplicate Host Management ##
      +## Duplicate host management ##
       
       There are situations where feeder hubs may have hosts with duplicate hostkeys:
       
      @@ -204,14 +192,14 @@ A few pre-requisites must be handled before enabling this utility:
       
       On Debian/Ubuntu:
       
      -``` bash
      -# apt install -qy python3 python3-urllib3
      +``` command
      +apt install -qy python3 python3-urllib3
       ```
       
       On RedHat/CentOS versions 7 and above:
       
      -``` bash
      -# yum install -qy python3 python3-urllib3
      +``` command
      +yum install -qy python3 python3-urllib3
       ```
       
       On RedHat/CentOS 6 you will have to install python3 manually and the install urllib3 with pip3.
      @@ -275,16 +263,16 @@ This class only has an effect on the superhub host.
       Please refer to `/var/cfengine/output`, `/var/log/postgresql.log` and
       `/opt/cfengine/federation/superhub/import/*.log.gz` when problems occur. Sending
       these logs to us in bug reports will help significantly as we fine tune the
      -Federated Reporting feature.
      +Federated reporting feature.
       
      -Also see [Disable Feeder][Federated Reporting#Disable Feeder] for information
      -about how to temporarily disable a feeder's participation in Federated Reporting
      +Also see [Disable feeder][Federated reporting#Disable feeder] for information
      +about how to temporarily disable a feeder's participation in Federated reporting
       in case that is causing an issue for the Feeder Hub.
       
      -## API Setup ##
      +## API setup ##
       
       An API may be used instead of the UI. This could be used to automate the setup
      -of infrastructure related to Federated Reporting and Feeder hubs.
      +of infrastructure related to Federated reporting and Feeder hubs.
       
       Command line examples follow using [curl](https://curl.haxx.se/) and
       [cf-remote](https://github.com/cfengine/cf-remote).
      @@ -334,20 +322,20 @@ administrative rights can make these requests. It is also possible to customize
       the RBAC settings to make a user who only has rights to the needed `api/fr`
       APIs.
       
      -```console
      -$ export PASSWORD="testingFR"
      +```command
      +export PASSWORD="testingFR"
       ```
       
       ### Enable superhub
       
      -```console
      -$ curl -k -i -s -X POST -u admin:$PASSWORD https://$SUPERHUB/api/fr/setup-hub/superhub
      +```command
      +curl -k -i -s -X POST -u admin:$PASSWORD https://$SUPERHUB/api/fr/setup-hub/superhub
       ```
       
       ### Enable feeder
       
      -```console
      -$ curl -k -i -s -X POST -u admin:$PASSWORD https://$FEEDER/api/fr/setup-hub/feeder
      +```command
      +curl -k -i -s -X POST -u admin:$PASSWORD https://$FEEDER/api/fr/setup-hub/feeder
       ```
       
       ### Enable feeder without API
      @@ -371,8 +359,8 @@ $
       
       ### Trigger agent run
       
      -```console
      -$ cf-remote sudo -H $CLOUD_USER$SUPERHUB,$CLOUD_USER$FEEDER "/var/cfengine/bin/cf-agent -KI"
      +```command
      +cf-remote sudo -H $CLOUD_USER$SUPERHUB,$CLOUD_USER$FEEDER "/var/cfengine/bin/cf-agent -KI"
       ```
       
       Ensure there are no errors in the agent run.
      @@ -455,7 +443,7 @@ $ curl -k -i -s -X POST -u admin:$PASSWORD https://$FEEDER/api/fr/federation-con
       (The second API call is needed to save the updated config to file,
       `federation-config.json`).
       
      -Note: for pre 3.14 feeders, you must [Add superhub to feeder without API][Federated Reporting#Add superhub to feeder without API]
      +Note: for pre 3.14 feeders, you must [Add superhub to feeder without API][Federated reporting#Add superhub to feeder without API]
       
       #### Add superhub to feeder without API
       
      @@ -544,8 +532,8 @@ The agent run on the feeder will configure ssh and generate a dump.
       The agent run on the superhub will pull the data and import it.
       Check that each step works without errors:
       
      -```console
      -$ cf-remote sudo -H $CLOUD_USER$FEEDER,$CLOUD_USER$SUPERHUB "/var/cfengine/bin/cf-agent -KI"
      +```command
      +cf-remote sudo -H $CLOUD_USER$FEEDER,$CLOUD_USER$SUPERHUB "/var/cfengine/bin/cf-agent -KI"
       ```
       
       ### Do a manual collection of superhub data
      @@ -562,8 +550,8 @@ $ cf-remote sudo -H $SUPERHUB "/var/cfengine/bin/cf-hub -I -H $SUPERHUB_BS --que
       
       Let's switch back to ordinary mode of periodic agent runs.
       
      -```console
      -$ cf-remote sudo -H $CLOUD_USER$SUPERHUB,$CLOUD_USER$FEEDER "systemctl start cf-execd"
      +```command
      +cf-remote sudo -H $CLOUD_USER$SUPERHUB,$CLOUD_USER$FEEDER "systemctl start cf-execd"
       ```
       
       On systems running systemd, we need to rename the binary back and start it manually.
      @@ -573,12 +561,12 @@ $ cf-remote sudo -H $CLOUD_USER$SUPERHUB,$CLOUD_USER$FEEDER "mv /var/cfengine/bi
       $ cf-remote sudo -H $CLOUD_USER$SUPERHUB,$CLOUD_USER$FEEDER "/var/cfengine/bin/cf-execd"
       ```
       
      -## Disable Feeder
      +## Disable feeder
       
       Edit Hub Disable
       
       A Feeder Hub may be disabled from the Hub Management app so that it will no
      -longer participate in Federated Reporting. No further attempts to pull data from
      +longer participate in Federated reporting. No further attempts to pull data from
       that feeder will occur until it is enabled again.
       
       Click the edit button for the feeder, enter URL and credentials information as
      @@ -591,9 +579,9 @@ The list of connected hubs should now reflect the disabled state.
       
       ## Uninstall
       
      -Uninstalling Federated Reporting from a superhub is not possible at this time.
      +Uninstalling Federated reporting from a superhub is not possible at this time.
       
      -In order to remove Federated Reporting from a feeder you must set the `target_state`
      +In order to remove Federated reporting from a feeder you must set the `target_state`
       to `off`. On the next agent run the `cftransport` user will be removed, thus removing
       the trust established with the superhub and causing no further dump/import procedures
       to occur.
      @@ -617,14 +605,14 @@ There are two ways to change the `target_state` of a feeder.
       
       2. Change the state of the feeder:
       
      -  ```console
      -  $ curl -k -i -s -X PUT -u admin:$PASSWORD https://$FEEDER/api/fr/hub-state -d @target-state-off.json --header "Content-Type: application/json"
      +  ```command
      +  curl -k -i -s -X PUT -u admin:$PASSWORD https://$FEEDER/api/fr/hub-state -d @target-state-off.json --header "Content-Type: application/json"
         ```
       
       3. **Save the federation config:**
       
      -  ```console
      -  $ curl -k -i -s -X POST -u admin:$PASSWORD https://$FEEDER/api/fr/federation-config
      +  ```command
      +  curl -k -i -s -X POST -u admin:$PASSWORD https://$FEEDER/api/fr/federation-config
         ```
       
       ### Uninstall without API
      @@ -649,7 +637,7 @@ you wish to disable and change the top-level `target_state` property value to `o
       }
       ```
       
      -### Remove Feeder from Mission Portal Hub Management
      +### Remove feeder from Mission Portal hub management
       
       At this time it is not possible to remove a connected hub in the Mission Portal Hub
       management app.
      @@ -657,8 +645,8 @@ management app.
       * List all feeders to find the id value. Use of ```jq``` is optional for pretty printing the JSON.
       
          (Set approprivate values in your shell for `PASSWORD` and `SUPERHUB`)
      -   ```console
      -   $ curl -k -s -X GET -u admin:$PASSWORD https://$SUPERHUB/api/fr/remote-hub | jq '.'
      +   ```command
      +   curl -k -s -X GET -u admin:$PASSWORD https://$SUPERHUB/api/fr/remote-hub | jq '.'
          ```
       
          ```json
      @@ -706,16 +694,16 @@ we use the number "1".
       
       * Remove the feeder from `/opt/cfengine/federation/cfapache/federation-config.json`. Replace "id-1" below with the appropriate id from the previous steps.
       
      -   ```console
      -   root@superhub: ~# contents=$(jq 'del(.remote_hubs ."id-1")' /opt/cfengine/federation/cfapache/federation-config.json) && echo "${contents}" > /opt/cfengine/federation/cfapache/federation-config.json
      +   ```command
      +   contents=$(jq 'del(.remote_hubs ."id-1")' /opt/cfengine/federation/cfapache/federation-config.json) && echo "${contents}" > /opt/cfengine/federation/cfapache/federation-config.json
          ```
       
       * Remove items associated with this feeder in the `cfdb` database.
       
           Determine the cfdb-specific `hub_id`.
       
      -   ```console
      -   root@superhub: ~# /var/cfengine/bin/psql cfdb -c "select * from __hubs"
      +   ```command
      +   /var/cfengine/bin/psql cfdb -c "select * from __hubs"
          ```
       
          Typical output would be like the following.
      @@ -760,7 +748,7 @@ we use the number "1".
          root@feeder: ~# /var/cfengine/bin/psql cfsettings -c 'TRUNCATE federated_reporting_settings'
          ```
       
      -## Superhub Upgrade ##
      +## Superhub upgrade ##
       
       Starting with 3.15.6 and 3.18.2 superhubs can be directly upgraded by installing the new hub package.
       
      @@ -771,7 +759,7 @@ For versions 3.15.5, and 3.18.1 and older the superhub can not be directly upgra
       Typically the superhub doesn't have unique information or serve policy.
       This makes it reasonable and easy to upgrade the superhub with a fresh install.
       If there are unique items like custom reports, dashboards, alerts or conditions on the superhub which need to be preserved
      -you may use the [Import & Export API] or Mission Portal Settings UI to export and then import after upgrading.
      +you may use the [Import & export API] or Mission Portal Settings UI to export and then import after upgrading.
       
       Follow this procedure:
       
      @@ -779,39 +767,38 @@ Follow this procedure:
       * Export any items from Mission Portal you wish to migrate
       * Stop all CFEngine services on the superhub
       
      -   ```console
      -   # systemctl stop cfengine3
      +   ```command
      +   systemctl stop cfengine3
          ```
       
       * Uninstall CFEngine hub
       
      -   ```console
      -   # rpm -e cfengine-nova-hub
      +   ```command
      +   rpm -e cfengine-nova-hub
          ```
       
          or
       
      -   ```console
      -   # apt-get remove cfengine-nova-hub
      +   ```command
      +   apt-get remove cfengine-nova-hub
          ```
       
       * Cleanup directories
       
      -   ```console
      -   # rm -rf /var/cfengine
      -   # rm -rf /opt/cfengine
      +   ```command
      +   rm -rf /var/cfengine /opt/cfengine
          ```
       * Install new version of cfengine
       * Confirm succesful installation
       
      -   ```console
      -   # grep -i err /var/log/CFEngineInstall.log
      +   ```command
      +   grep -i err /var/log/CFEngineInstall.log
          ```
       
       * Bootstrap the superhub to itself
       
      -   ```console
      -   # cf-agent --bootstrap 
      +   ```command
      +   cf-agent --bootstrap 
          ```
       
       * Reconfigure all feeders (3.15 series and newer, skip for 3.12 series feeder hubs)
      @@ -829,13 +816,13 @@ Follow this procedure:
       
          * On 3.15.x and greater feeders, also truncate the `remote_hubs` table:
       
      -      ```console
      -      # /var/cfengine/bin/psql cfsettings -c 'TRUNCATE remote_hubs'
      +      ```command
      +      /var/cfengine/bin/psql cfsettings -c 'TRUNCATE remote_hubs'
             ```
      -* Reinstall and configure the superhub as described in [Installation][Federated Reporting#Installation]
      -* Import any saved information into Mission Portal via the [Import & Export API] or Mission Portal Settings UI
      +* Reinstall and configure the superhub as described in [Installation][Federated reporting#Installation]
      +* Import any saved information into Mission Portal via the [Import & export API] or Mission Portal Settings UI
       * Wait 20 minutes for federated reporting to be updated from feeders to superhub
       
         or
       
      -  * run `cf-agent -KI` on each feeder, and then `cf-agent -KI` on the superhub to manually force a Federated Reporting collection cycle.
      +  * run `cf-agent -KI` on each feeder, and then `cf-agent -KI` on the superhub to manually force a Federated reporting collection cycle.
      diff --git a/web-ui/fr-edit-hub-disable.png b/web-ui/fr-edit-hub-disable.png
      index faa26396a..4e1bdbb62 100644
      Binary files a/web-ui/fr-edit-hub-disable.png and b/web-ui/fr-edit-hub-disable.png differ
      diff --git a/web-ui/health.markdown b/web-ui/health.markdown
      index b31cd46cd..334585db3 100644
      --- a/web-ui/health.markdown
      +++ b/web-ui/health.markdown
      @@ -3,17 +3,19 @@ layout: default
       title: Health
       sorting: 20
       published: true
      -tags: [cfengine enterprise, user interface, mission portal, health]
       ---
       
       
       
       You can get quick access to the health of hosts, including direct links to reports, from the Health drop down at the top of every Enterprise UI screen. Hosts are listed as unhealthy if:
       
      -* the hub was not able to connect to and collect data from the host within a set time interval (unreachable host). The time interval can be set in the Mission Portal settings.
      -* the policy did not get executed for the last three runs. This could be caused by `cf-execd` not running on the host (scheduling deviation) or an error in policy that stops its execution. The hub is still able to contact the host, but it will return stale data because of this deviation.
      -* two or more hosts use the same key. This is detected by "reporting cookies", randomized tokens generated every report collection. If the client presents a mismatching cookie (compared to last collection) a collision is detected. The number of collisions (per hostkey) that cause the unhealthy status is configurable in [settings][Settings#Preferences].
      -* reports have recently been collected, but cf-agent has not recently run. "Recently" is defined by the configured run-interval of their cf-agent.
      +* Missing reporting data : Host has connected to hub (to get policy), but reports have never been collected from it.
      +* Unreachable hosts : Reports from host has been collected in the past, but not recently (as defined by "Unreachable host threshold").
      +* Outdated reporting data : The host is communicating correctly and sending its reports, but the data is outdated (there are no recent reports), indicating that there hasn't been any policy runs recently (performed by the cf-agent binary). There is no data to prove that your policy, describing your desired state, is being successfully enforced.
      +* Policy errors : Reports have recently been collected and cf-agent has completed a run with an error.
      +* Duplicate IDs : CFEngine hosts are identified by the CFEngine key they use. If two or more hosts use the same key the reports will be very unreliable. This is detected by exchanging randomized cookies(tokens) during report collections. If a client sends a mismatching cookie (compared to last collection), it indicates that multiple hosts are using the same ID.
      +* Duplicate hostnames: multiple host identities reporting the same host identifier (by default hostname derived from `default:sys.fqhost` variable but changeable in Settings -> Host identifier)
      +
       
       These categories are non-overlapping, meaning a host will only appear in one category at at time even if conditions satisfying multiple categories might be present. This makes reports simpler to read, and makes it easier to detect and fix the root cause of the issue. As one issue is resolved the host might then move to another category.
      -In either situation the data from that host will be from old runs and probably not reflect the current state of that host.
      +Regardless of the situation, the data from the host will be from the latest report collection, representing the most recent known state of the host.
      diff --git a/web-ui/host-specific-data-classes.png b/web-ui/host-specific-data-classes.png
      new file mode 100644
      index 000000000..b0c64781f
      Binary files /dev/null and b/web-ui/host-specific-data-classes.png differ
      diff --git a/web-ui/host-specific-data-variables.png b/web-ui/host-specific-data-variables.png
      new file mode 100644
      index 000000000..340feb654
      Binary files /dev/null and b/web-ui/host-specific-data-variables.png differ
      diff --git a/web-ui/host-specific-data.png b/web-ui/host-specific-data.png
      deleted file mode 100644
      index 8d40eb6ed..000000000
      Binary files a/web-ui/host-specific-data.png and /dev/null differ
      diff --git a/web-ui/hosts.markdown b/web-ui/hosts.markdown
      index 50af051fb..0af521f28 100644
      --- a/web-ui/hosts.markdown
      +++ b/web-ui/hosts.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Hosts
       sorting: 30
       published: true
      -tags: [cfengine enterprise, user interface, mission portal]
       ---
       
       The Hosts app provides a customizable global overview of _promise_ compliance. A summary of compliant vs non-compliant hosts is provided at each branch in the tree.
      @@ -15,31 +14,37 @@ Each host is in one of two groups: out of compliance or fully compliant.
       
       Hosts app overview
       
      -A host tree based on OS (Operating system) is present by default. Host trees map hosts based on reported classes into a hierarchy. Additional host trees can be added based on classes, which could be used to view different perspectives such as geographic location, production tier, business unit, etc.... Furthermore, Each host tree can be shared based on Mission Portal role.
      +A host tree based on OS (Operating system) is present by default. Host trees map hosts based on reported classes into a hierarchy. Additional host trees can be added based on classes, which could be used to view different perspectives such as geographic location, production tier, business unit, etc. Furthermore, each host tree can be shared based on Mission Portal role.
       
       Hosts app custom tree for geographic region
       
       Visiting a leaf node provides a summary of host specific information.
       
      -## Host Info ##
      +## Host info ##
       
       The host info page provides extensive information for an individual host.
       
       Host info page
       
      -### Host Actions ###
      +### Host actions ###
       
       Take action on a host.
       
       Host action buttons
       
       * Run agent :: Request an unscheduled policy run
      -* Collect reports:: Request report collection
      -* Get URL:: Get the URL to the specific hosts info page
      +* Collect reports :: Request report collection
      +* Get URL :: Get the URL to the specific hosts info page
       * Delete host :: Delete the host
       
       ### Host specific data ###
       
       Assign host specific _Variables_ and _Classes_.
       
      -Host specific data
      +Host specific data variables
      +
      +Note: When defined via host specific data, variables default to the `variables` _bundle_ of the `data` _namespace_. Qualify the variable with the desired bundle and namespace to override the default. For example `my_bundle.myvariable` to define `my_bundle.myvariable` in the `data` namespace, or `my_namespace:my_bundle.myvariable` to define `myvariable` in the `my_bundle` bundle of the `my_namespace` namespace.
      +
      +Host specific data classes
      +
      +Note: When defined via host specific data classes default to the `data` _namespace_. Qualify the class with the desired namespace to override the default. For example `default:my_class`, or `my_namespace:my_class`.
      diff --git a/web-ui/hub_administration.markdown b/web-ui/hub_administration.markdown
      index 142e462fc..cc6265e2e 100644
      --- a/web-ui/hub_administration.markdown
      +++ b/web-ui/hub_administration.markdown
      @@ -1,11 +1,10 @@
       ---
       layout: default
      -title: Hub Administration
      +title: Hub administration
       published: true
       sorting: 80
      -tags: [cfengine enterprise, hub administration]
       ---
       
       Find out how to perform common hub administration tasks like
       [resetting admin credentials][Reset administrative credentials], or
      -[using custom SSL certificates][Custom SSL Certificate].
      +[using custom SSL certificates][Custom SSL certificate].
      diff --git a/web-ui/hub_administration/adjusting-schedules.markdown b/web-ui/hub_administration/adjusting-schedules.markdown
      index 3f064e151..0b74d9540 100644
      --- a/web-ui/hub_administration/adjusting-schedules.markdown
      +++ b/web-ui/hub_administration/adjusting-schedules.markdown
      @@ -1,8 +1,7 @@
       ---
       layout: default
      -title: Adjusting Schedules
      +title: Adjusting schedules
       published: true
      -tags: [cfengine enterprise, hub administration, scheduling, cf-execd, cf-agent, cf-hub]
       ---
       
       ## Set cf-execd agent execution schedule
      diff --git a/web-ui/hub_administration/backup-and-restore.markdown b/web-ui/hub_administration/backup-and-restore.markdown
      index c92ecac80..4b24d95c4 100644
      --- a/web-ui/hub_administration/backup-and-restore.markdown
      +++ b/web-ui/hub_administration/backup-and-restore.markdown
      @@ -1,14 +1,13 @@
       ---
       layout: default
      -title: Backup and Restore
      +title: Backup and restore
       published: true
      -tags: [cfengine enterprise, hub administration, backup, restore]
       ---
       
       With policy stored in version control there are few things that should be
       preserved in your backup and restore plan.
       
      -## Hub Identity
      +## Hub identity
       
       CFEngines trust model is based on public and private key exchange. In order to
       re-provision a hub and for remote agents to retain trust the hubs key pair must
      @@ -19,7 +18,7 @@ Include `$(sys.workdir)/ppkeys/localhost.pub` and
       
       **Note:** This is the most important thing to backup.
       
      -## Hub License
      +## Hub license
       
       Enterprise hubs will collect for up to the licensed number of hosts. When
       re-provisioning a hub you will need the license that matches the hub identity in
      @@ -27,7 +26,7 @@ order to be able to collect reports for more than 25 hosts.
       
       Include `$(sys.workdir)/licenses` in your backup plan.
       
      -## Hub Databases
      +## Hub databases
       
       Data collected from remote hosts and configuration information for Mission
       Portal is stored on the hub in PostgreSQL which can be backed up and restored
      @@ -36,20 +35,20 @@ using standard tools.
       If you wish to rebuild a hub and
       restore the history of policy outcomes you must backup and restore.
       
      -### Host Data
      +### Host data
       
       `cfdb` stores data related to policy runs on your hosts for example host inventory.
       
       **Backup:**
       
      -```console
      -# pg_dump -Fc cfdb > cfdb.bak
      +```command
      +pg_dump -Fc cfdb > cfdb.bak
       ```
       
       **Restore:**
       
      -```console
      -# pg_restore -Fc cfdb.bak
      +```command
      +pg_restore -Fc cfdb.bak
       ```
       
       ### Mission Portal
      diff --git a/web-ui/hub_administration/custom-https-certificate.markdown b/web-ui/hub_administration/custom-https-certificate.markdown
      index d5bc82fb9..9deaf7ef2 100644
      --- a/web-ui/hub_administration/custom-https-certificate.markdown
      +++ b/web-ui/hub_administration/custom-https-certificate.markdown
      @@ -1,15 +1,14 @@
       ---
       layout: default
      -title: Custom SSL Certificate
      +title: Custom SSL certificate
       published: true
      -tags: [cfengine enterprise, hub administration, SSL]
       ---
       
       When first installed a self-signed ssl certificate is automatically generated
       and used to secure Mission Portal and API communications. You can change this
       certificate out with a custom one by replacing
       `/var/cfengine/httpd/ssl/certs/.cert` and
      -`/var/cfengine/httpd/ssl/private/.cert` where hostname is the fully
      +`/var/cfengine/httpd/ssl/private/.key` where hostname is the fully
       qualified domain name of the host.
       
       After installing the certificate please make sure that the certificate
      @@ -20,12 +19,16 @@ You can test by verifying you can access the certificate with a unprivileged use
       You can get the fully qualified hostname on your hub by running the following
       commands.
       
      -```console
      -[root@hub ~]# cf-promises --show-vars=default:sys\.fqhost
      +```command
      +cf-promises --show-vars=default:sys\.fqhost
      +```
      +```output
       default:sys.fqhost                       hub                                                          inventory,source=agent,attribute_name=Host name
       ```
       
      -```console
      -[root@hub ~]# hostname -f
      +```command
      +hostname -f
      +```
      +```output
       hub
       ```
      diff --git a/web-ui/hub_administration/custom-ldap-port.markdown b/web-ui/hub_administration/custom-ldap-port.markdown
      index b1017d8bb..8fd3ea7de 100644
      --- a/web-ui/hub_administration/custom-ldap-port.markdown
      +++ b/web-ui/hub_administration/custom-ldap-port.markdown
      @@ -2,7 +2,6 @@
       layout: default
       title: Configure a custom LDAP port
       published: true
      -tags: [cfengine enterprise, hub administration, ldap]
       ---
       
       Mission Portals User settings and preferences provides a radio button
      @@ -13,7 +12,7 @@ encryption. This controls the encryption and the port to connect to.
       If you want to configure LDAP authentication to use a custom port you can do so
       via the Status and Setting REST API.
       
      -Status and Settings REST API
      +Status and settings REST API
       This example shows using jq to preserve the existing settings and update the
       SSL LDAP port to `3269`.
       
      diff --git a/web-ui/hub_administration/custom-ldaps-certificate.markdown b/web-ui/hub_administration/custom-ldaps-certificate.markdown
      index 39eb0748e..fa43bfb6e 100644
      --- a/web-ui/hub_administration/custom-ldaps-certificate.markdown
      +++ b/web-ui/hub_administration/custom-ldaps-certificate.markdown
      @@ -1,8 +1,7 @@
       ---
       layout: default
      -title: Custom LDAPs Certificate
      +title: Custom LDAPs certificate
       published: true
      -tags: [cfengine enterprise, hub administration, LDAP, authentication]
       ---
       
       To use a custom LDAPs certificate install it into your hubs operating system.
      @@ -11,6 +10,6 @@ Note you can use the `LDAPTLS_CACERT` environment variable to use a custom
       certificate for testing with `ldapsearch` before it has been installed into the
       system.
       
      -```console
      -[root@hub]:~# env LDAPTLS_CACERT=/tmp/MY-LDAP-CERT.cert.pem ldapsearch -xLLL -H ldaps://ldap.example.local:636 -b "ou=people,dc=example,dc=local"
      +```command
      +env LDAPTLS_CACERT=/tmp/MY-LDAP-CERT.cert.pem ldapsearch -xLLL -H ldaps://ldap.example.local:636 -b "ou=people,dc=example,dc=local"
       ```
      diff --git a/web-ui/hub_administration/decommissioning-hosts.markdown b/web-ui/hub_administration/decommissioning-hosts.markdown
      index 995577d37..747cb7e5a 100644
      --- a/web-ui/hub_administration/decommissioning-hosts.markdown
      +++ b/web-ui/hub_administration/decommissioning-hosts.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Decommissioning hosts
       sorting: 30
       published: true
      -tags: [cfengine enterprise, user interface, mission portal]
       ---
       
       Once a host is shut off, or CFEngine is uninstalled, you should remove it from Mission Portal.
      @@ -36,14 +35,14 @@ Please note that:
       
       Single hosts can be removed by visiting the host info page, and clicking the trash can next to the host identifier (header):
       
      -![Remove host](../Mission-portal-remove-host.png)
      +![Remove host](./Mission-portal-remove-host.png)
       
       ## Host removal through Enterprise API ##
       
       If you decommission hosts regularly, it can be cumbersome to use the UI for every host.
       Decommissioning can be done via API, for example using curl:
       
      -```
      +```command
       curl --user admin:admin http://127.0.0.1/api/host/cf-key -r SHA=92eff6add6e8add0bb51f1af52d8f56ed69b56ccdca27509952ae07fe5b2997b -X DELETE
       ```
       
      @@ -56,7 +55,7 @@ This method is generally not recommended on the CFEngine Enterprise Hub, as it *
       
       The `cf-key` binary allows you to delete hosts from the `cf_lastseen.lmdb` database and `ppkeys`:
       
      -```
      +```command
       cf-key -r SHA=92eff6add6e8add0bb51f1af52d8f56ed69b56ccdca27509952ae07fe5b2997b
       ```
       
      diff --git a/web-ui/hub_administration/enable-plain-http.markdown b/web-ui/hub_administration/enable-plain-http.markdown
      index 1b132b153..7de763a7b 100644
      --- a/web-ui/hub_administration/enable-plain-http.markdown
      +++ b/web-ui/hub_administration/enable-plain-http.markdown
      @@ -2,7 +2,6 @@
       layout: default
       title: Enable plain http
       published: true
      -tags: [cfengine enterprise, hub administration, SSL]
       ---
       
       By default HTTPS is enforced by redirecting any non secure connection requests.
      @@ -13,7 +12,8 @@ If you would like to enable plain HTTP you can do so by defining
       For example, simply place the following inside `def.json` in the root of your
       masterfiles.
       
      -```
      +```json
      +[file=def.json]
       {
         "classes": {
           "cfe_enterprise_enable_plain_http": [ "any" ]
      diff --git a/web-ui/hub_administration/extending-mission-portal.markdown b/web-ui/hub_administration/extending-mission-portal.markdown
      index db4792a90..d0d15a239 100644
      --- a/web-ui/hub_administration/extending-mission-portal.markdown
      +++ b/web-ui/hub_administration/extending-mission-portal.markdown
      @@ -3,7 +3,6 @@ layout: default
       title: Extending Mission Portal
       published: true
       sorting: 90
      -tags: [faq, mission portal, hub administration]
       ---
       
       ## Custom pages requiring authenticated users
      @@ -44,6 +43,7 @@ Use the following structure in your HTML to style the page the same as the rest
       of Mission Portal.
       
       ```html
      +[file=file_name.html]
       

      PAGE TITLE

      diff --git a/web-ui/hub_administration/extending-query-builder.markdown b/web-ui/hub_administration/extending-query-builder.markdown index a7cd22cc3..b0040fcf0 100644 --- a/web-ui/hub_administration/extending-query-builder.markdown +++ b/web-ui/hub_administration/extending-query-builder.markdown @@ -1,12 +1,11 @@ --- layout: default -title: Extending Query Builder in Mission Portal +title: Extending query builder in Mission Portal published: true sorting: 90 -tags: [faq, mission portal, hub administration, query builder] --- -This instruction is created to explain how to extend the [Query Builder][Reporting UI#Query Builder] in the case where +This instruction is created to explain how to extend the [Query builder][Reporting UI#Query builder] in the case where the enterprise hub database has new or custom tables that you want to use on the reporting page. The workflow in this guide is to edit a file that will be updated by CFEngine when you upgrade to a newer version of CFEngine. @@ -14,7 +13,7 @@ Thus your changes are going to be deleted. Please make sure to either keep a cop or add a relative file path `scripts/advancedreports/dca.js` to `$(sys.workdir)/httpd/htdocs/preserve_during_upgrade.txt` to preserve `dca.js` during the CFEngine upgrade process. -### How to add new table to Query Builder +### How to add new table to query builder To extend the query builder with your custom data you need to edit the javascript file located on your hub here: `$(sys.workdir)/share/GUI/scripts/advancedreports/dca.js`. @@ -135,7 +134,7 @@ Let's see an example of Query builder extending with a new test table. 1. Create a new table in the cfdb database -``` +```sql CREATE TABLE IF NOT EXISTS "test" ( "hostkey" text PRIMARY KEY, "random_number" integer NOT NULL, @@ -145,7 +144,7 @@ CREATE TABLE IF NOT EXISTS "test" ( 2. Fill the table with data from the hosts. -``` +```sql INSERT INTO "test" SELECT "hostkey", (random() * 100)::int as random_number FROM "__hosts"; ``` @@ -186,7 +185,7 @@ INSERT INTO "test" SELECT "hostkey", (random() * 100)::int as random_number FRO } ``` -4. See the result in the Query Builder +4. See the result in the Query builder After the next cf-agent run file should be changed in the Mission Portal and you will be able to see the new table in the Query builder. You can use this table as predefined ones. diff --git a/web-ui/hub_administration/lookup-license-info.markdown b/web-ui/hub_administration/lookup-license-info.markdown index c213e6db5..466cb515b 100644 --- a/web-ui/hub_administration/lookup-license-info.markdown +++ b/web-ui/hub_administration/lookup-license-info.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Lookup License Info +title: Lookup license info published: true -tags: [cfengine enterprise, hub administration, license] --- Information about the currently issued license can be obtained from the About section in Mission Portal web interface or from the command line as shown here. @@ -18,16 +17,18 @@ source of data. Run from the hub itself. -```console -$ curl -u admin http://localhost/api/ +```command +curl -u admin http://localhost/api/ ``` # Get license info from cf-hub Run as `root` from the hub itself. -```console -[root@hub ~]# cf-hub --show-license +```command +cf-hub --show-license +``` +```output License file: /var/cfengine/licenses/hub-SHA=d13c14c3dc46ef1c5824eb70ffae3a1d1c67c7ce70a1e8e8634b1324d0041131.dat License status: Valid License count: 50 diff --git a/web-ui/hub_administration/policy-deployment.markdown b/web-ui/hub_administration/policy-deployment.markdown index a03a688a2..3b58c6547 100644 --- a/web-ui/hub_administration/policy-deployment.markdown +++ b/web-ui/hub_administration/policy-deployment.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Policy Deployment +title: Policy deployment published: true -tags: [cfengine enterprise, hub administration] --- By default CFEngine policy is distributed from `/var/cfengine/masterfiles` on @@ -55,6 +54,7 @@ The last option, a read-only login, is the best approach as it removes the possi To configure the upstream repository. You must provide the uri and a refspec (branch name usually). Credentials can be specified in several ways as mentioned above so pick your choice above and enter in only the needed information in the form. +If your CFEngine policies are not located in the repository root, you can specify the path in the "Project subdirectory" text input field. ### Configuring upstream VCS via Mission Portal @@ -81,11 +81,13 @@ update policy. For example: -```console -[root@hub ~]# cf-agent -KIf update.cf --define cfengine_internal_masterfiles_update - info: Executing 'no timeout' ... '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' - info: Command related to promiser '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' returned code defined as promise kept 0 - info: Completed execution of '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' +```command +cf-agent -KIf update.cf --define cfengine_internal_masterfiles_update +``` +```output +info: Executing 'no timeout' ... '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' +info: Command related to promiser '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' returned code defined as promise kept 0 +info: Completed execution of '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' ``` This is useful if you would like more manual control of policy releases. @@ -99,7 +101,8 @@ To configure automatic deployments simply ensure the Create `def.json` in the root of your masterfiles with the following content: -``` +```json +[file=def.json] { "classes": { "cfengine_internal_masterfiles_update": [ "hub" ] @@ -112,6 +115,7 @@ Create `def.json` in the root of your masterfiles with the following content: Simply edit `bundle common update_def` in `controls/update_def.cf`. ```cf3 +[file=update_def.cf] bundle common update_def { # ... @@ -131,8 +135,10 @@ will not be deployed. For example: -```console -[root@hub ~]# cf-agent -KIf update.cf --define cfengine_internal_masterfiles_update +```command +cf-agent -KIf update.cf --define cfengine_internal_masterfiles_update +``` +```output info: Executing 'no timeout' ... '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' error: Command related to promiser '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' returned code defined as promise failed 1 info: Completed execution of '/var/cfengine/httpd/htdocs/api/dc-scripts/masterfiles-stage.sh' @@ -146,8 +152,10 @@ Policy deployments are logged to `/var/cfengine/outputs/dc-scripts.log`. The logs contain useful information about the failed deployment. For example here I can see that there is a syntax error in `promises.cf` near line 14. -```console -[root@prihub ~]# tail -n 5 /var/cfengine/outputs/dc-scripts.log +```command +tail -n 5 /var/cfengine/outputs/dc-scripts.log +``` +```output /opt/cfengine/masterfiles_staging_tmp/promises.cf:14:46: error: Expected ',', wrong input '@(inventory.bundles)' @(inventory.bundles), ^ diff --git a/web-ui/hub_administration/public-key-distribution.markdown b/web-ui/hub_administration/public-key-distribution.markdown index aa2094008..a8ae2c7a3 100644 --- a/web-ui/hub_administration/public-key-distribution.markdown +++ b/web-ui/hub_administration/public-key-distribution.markdown @@ -2,7 +2,6 @@ layout: default title: Public key distribution published: true -tags: [cfengine enterprise, hub administration, key distribution, trust establishment] --- > How can I arrange for the hosts in my infrastructure to trust a new key? @@ -29,6 +28,7 @@ policy server and automatically installed on all hosts. ```cf3 +[file=trust_distkeys.cf] bundle agent trust_distkeys #@ brief Example public key distribution { diff --git a/web-ui/hub_administration/regenerate-self-signed-cert.markdown b/web-ui/hub_administration/regenerate-self-signed-cert.markdown index 0acab9bac..50dbbd315 100644 --- a/web-ui/hub_administration/regenerate-self-signed-cert.markdown +++ b/web-ui/hub_administration/regenerate-self-signed-cert.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Regenerate Self Signed SSL Certificate +title: Regenerate self signed SSL certificate published: true -tags: [cfengine enterprise, hub administration, SSL] --- When first installed a self-signed ssl certificate is automatically generated @@ -11,8 +10,8 @@ this certificate by running `cfe_enterprise_selfsigned_cert` bundle with the `_cfe_enterprise_selfsigned_cert_regenerate_cert` class defined. This can be done by running the following commands as root on the hub. -```console -# cf-agent --no-lock --inform \ +```command +cf-agent --no-lock --inform \ --bundlesequence cfe_enterprise_selfsigned_cert \ --define _cfe_enterprise_selfsigned_cert_regenerate_certificate ``` diff --git a/web-ui/hub_administration/reinstall.markdown b/web-ui/hub_administration/reinstall.markdown index 2f2ab0ed9..20ee13f6e 100644 --- a/web-ui/hub_administration/reinstall.markdown +++ b/web-ui/hub_administration/reinstall.markdown @@ -1,8 +1,7 @@ --- layout: default -title: Re-installing Enterprise Hub +title: Re-installing Enterprise hub published: true -tags: [cfengine enterprise, hub administration, re-install] --- Sometimes it is useful to re-install the hub while still preserving existing diff --git a/web-ui/hub_administration/reset-admin-creds.markdown b/web-ui/hub_administration/reset-admin-creds.markdown index 589fa6f6d..232cb39e1 100644 --- a/web-ui/hub_administration/reset-admin-creds.markdown +++ b/web-ui/hub_administration/reset-admin-creds.markdown @@ -2,14 +2,13 @@ layout: default title: Reset administrative credentials published: true -tags: [cfengine enterprise, hub administration, credentials] --- The default `admin` user can be reset to defaults using the following SQL. -cfsettings-setadminpassword.sql: ```sql +[file=cfsettings-setadminpassword.sql] INSERT INTO "users" ("username", "password", "salt", "name", "email", "external", "active", "roles", "changetimestamp") SELECT 'admin', 'SHA=aa459b45ecf9816d472c2252af0b6c104f92a6faf2844547a03338e42e426f52', 'eWAbKQmxNP', 'admin', 'admin@organisation.com', false, '1', '{admin,cf_remoteagent}', now() ON CONFLICT (username, external) DO UPDATE @@ -19,8 +18,8 @@ ON CONFLICT (username, external) DO UPDATE To reset the CFEngine admin user run the following sql as root on your hub -```console -root@hub:~# psql cfsettings < cfsettings-setadminpassword.sql +```command +psql cfsettings < cfsettings-setadminpassword.sql ``` ## Internal credentials @@ -40,8 +39,8 @@ If these credentials are not synchronized properly you can get "Authentication f To rotate these credentials execute the following shell script on the hub and then restart the system with `systemctl restart cfengine3` or similar. ```bash +[file=rotate_mp_credentials.sh] #!/usr/bin/env bash -# rotate_mp_credentials.sh pwgen() { dd if=/dev/urandom bs=1024 count=1 2>/dev/null | tr -dc 'a-zA-Z0-9' | fold -w $1 | head -n 1 } @@ -67,8 +66,8 @@ If these credentials are out of sync or incorrect you will see errors like "500 Execute the following shell script to rotate and synchronize the CFE Robot credentials and then restart the system with `systemctl restart cfengine3` or similar. ```bash +[file=rotate_cfrobot_credentials.sh] #!/usr/bin/env bash -# rotate_cfrobot_credentials.sh pwgen() { dd if=/dev/urandom bs=1024 count=1 2>/dev/null | tr -dc 'a-zA-Z0-9' | fold -w $1 | head -n 1 } diff --git a/web-ui/hub_administration/settings-vcs.png b/web-ui/hub_administration/settings-vcs.png index cf58f4c0d..eefa7220a 100644 Binary files a/web-ui/hub_administration/settings-vcs.png and b/web-ui/hub_administration/settings-vcs.png differ diff --git a/web-ui/inventory-hover.png b/web-ui/inventory-hover.png deleted file mode 100644 index 2c71e78da..000000000 Binary files a/web-ui/inventory-hover.png and /dev/null differ diff --git a/web-ui/license-info.png b/web-ui/license-info.png new file mode 100644 index 000000000..bf9dd5273 Binary files /dev/null and b/web-ui/license-info.png differ diff --git a/web-ui/license-status-report.png b/web-ui/license-status-report.png new file mode 100644 index 000000000..5f7de78a1 Binary files /dev/null and b/web-ui/license-status-report.png differ diff --git a/web-ui/license.markdown b/web-ui/license.markdown new file mode 100644 index 000000000..0edab3df5 --- /dev/null +++ b/web-ui/license.markdown @@ -0,0 +1,17 @@ +--- +layout: default +title: License +published: true +--- + +## License information + +License information can be obtained from the About page under the user menu. + +Information about installed license. + +## License status report + +Click on the host count in the header to open the License Status Report. It contains information about the current license utilization. + +Report showing current license utilization. diff --git a/web-ui/measurements.markdown b/web-ui/measurements.markdown index 44aa58ea3..339d8b5ad 100644 --- a/web-ui/measurements.markdown +++ b/web-ui/measurements.markdown @@ -4,7 +4,6 @@ title: Measurements app alias: Measurements sorting: 70 published: true -tags: [cfengine enterprise, user interface, mission portal] --- Measurements allows you to get an overview of specific metrics on your hosts over time. diff --git a/web-ui/settings.markdown b/web-ui/settings.markdown index 2bd5b6d89..f9614ee09 100644 --- a/web-ui/settings.markdown +++ b/web-ui/settings.markdown @@ -3,29 +3,14 @@ layout: default title: Settings sorting: 10 published: true -tags: [cfengine enterprise, user interface, mission portal] --- A variety of CFEngine and system properties can be changed in the Settings view. -* [Opening Settings][Settings#Opening Settings] -* [Preferences][Settings#Preferences] -* [User Management][Settings#User Management] -* [Role Management][Settings#Role Management] -* [Manage Apps][Settings#Manage Apps] -* [Version Control Repository][Settings#Version Control Repository] -* [Host Identifier][Settings#Host Identifier] -* [Mail Settings][Settings#Mail settings] -* [Authentication settings][Settings#Authentication settings] -* [Export/Import][Settings#Export/Import] -* [Role based access control][Settings#Role based access control] -* [About CFEngine][Settings#About CFEngine] +## Opening settings ## - -## Opening Settings ## - -Opening Settings +Opening settings Settings are accessible from any view of the mission portal, from the drop down in the top right hand corner. @@ -45,18 +30,17 @@ administrator to change various options, including: * Unreachable host threshold * Number of samples used to identify a duplicate identity * Log level -* Customize the user experience with the organization logo -## User Management ## +## User management ## -User Management +User management User management is for adding or adjusting CFEngine Enterprise UI users, including their name, role, and password. -## Role Management ## +## Role management ## -Role Management +Role management Roles limit access to host data and access to shared assets like saved reports and dashboards. @@ -72,15 +56,17 @@ if you have the admin role and a role that matches zero hosts, the user will not see any hosts in Mission Portal. A shared report will only be accessible to a user if the user has all roles that the report was restricted to. -In order to access a shared reports or dashboard the use must have all roles +In order to access a shared reports or dashboard the user must have all roles that the report or dashboard was shared with. In order to see a host, none of the classes reported by the host can match the class exclusions from any role the user has. -Users without a role will not be able to see any hosts in Mission -Portal. +Users without a role will not be able to see any hosts in Mission Portal. +Here is a set of example roles, users and the impact on each user will be able to view. + +### Example roles Role **suse**: - Class include: `SUSE` - Class exclude: empty @@ -98,39 +84,39 @@ Role **windows_ubuntu** - Class include: `ubuntu` - Class exclude: empty +### Example users User one has role `SUSE`. User two has roles `no_windows` and `cfengine_3`. User three has roles `windows_ubuntu` and `no_windows`. -A report shared with `SUSE` and `no_windows` will not be seen by any of the -listed users. +### What reports each user can view +A report shared with `SUSE` and `no_windows` will not be seen by any of the listed users. -A report shared with `no_windows` and `cfengine_3` will only be seen by user -two. +A report shared with `no_windows` and `cfengine_3` will only be seen by user two. A report shared with `SUSE` will be seen by user one. +### Which hosts each user can view User one will only be able to see hosts that report the `SUSE` class. -User two will be able to see all hosts that have **not** reported the `windows` -class. +User two will be able to see all hosts that have **not** reported the `windows` class. User three will only be able to see hosts that have reported the `ubuntu` class. -### Predefined Roles +### Predefined roles * ```admin``` - The admin role can see everything and do anything. * ```cf_remoteagent``` - This role allows execution of `cf-runagent`. -### Default Role +### Default role To set the default role, click Settings -> User management -> Roles. You can then select which role will be the default role for new users. DefaultRoleSelecting -**Behaviour of Default Role:** +**Behaviour of default role:** Any new users created in Mission Portal's local user database will have this new role assigned. @@ -142,24 +128,24 @@ In effect this allows you to set the default permissions for new users (e.g. whi AddNewUser -## Manage Apps ## +## Manage apps ## -Manage Apps +Manage apps Application settings can help adjust some of CFEngine Enterprise UI app features, including the order in which the apps appear and their status (on or off). -## Version Control Repository ## +## Version control repository ## -Version Control Repository +Version control repository The repository holding the organization's masterfiles can be adjusted -on the Version Control Repository screen. +on the Version control repository screen. -## Host Identifier ## +## Host identifier ## -Host Identifier +Host identifier Host identity for the server can be set within settings, and can be adjusted to refer to the FQDN, IP address, or an unqualified domain @@ -186,19 +172,15 @@ Configure outbound mail settings: Mission portal can authenticate against an external directory. -**Special Notes:** - -- LDAP API Url refers to the API CFEngine uses internally for authentication. - Most likely you will not alter the default value. - -- LDAP filter must be supplied. +**Special notes:** - LDAP Host refers is the IP or Hostname of your LDAP server. - +- LDAP filter must be supplied. - LDAP bind username should be the username used to bind and search the LDAP directory. It must be provided in distinguished name format. + Additionally, you can bind anonymously. -- Default roles for users is configured under [Role Management][Settings#Role Management]. +- Default roles for users is configured under [Role management][Settings#Role management]. ### LDAP groups syncing ### @@ -214,15 +196,15 @@ Mission portal can authenticate against an external directory. **Note:** Roles *must* be created in Mission Portal. Enabling LDAP group sync will not result in addition or removal of Mission Portal roles. -**See also:** [LDAP authentication REST API][LDAP authentication API], [Role Management][Settings#Role Management] +**See also:** [LDAP authentication REST API][LDAP authentication API], [Role management][Settings#Role management] -## Export/Import ## +## Export/import ## Mission Portal's configuration can be exported and imported. -Export/Import +Export/import -**See also:** [Export/Import API][Import & Export API] +**See also:** [Export/import API][Import & export API] ## Role based access control ## @@ -231,7 +213,7 @@ Mission Portal's configuration can be exported and imported. Roles in Mission portal can be restricted to perform only configured actions. Configure role-based access controls from settings. -**Special Notes:** +**Special notes:** - Admin role has all permissions by default. @@ -243,8 +225,8 @@ Configure role-based access controls from settings. To restore the CFEngine admin role permissions run the following sql as root on your hub -```console -root@hub:~# /var/cfengine/bin/psql cfsettings -c "INSERT INTO rbac_role_permission (role_id, permission_alias) (SELECT 'admin'::text as role_id, alias as permission_alias FROM rbac_permissions) ON CONFLICT (role_id, permission_alias) DO NOTHING;" +```command +/var/cfengine/bin/psql cfsettings -c "INSERT INTO rbac_role_permission (role_id, permission_alias) (SELECT 'admin'::text as role_id, alias as permission_alias FROM rbac_permissions) ON CONFLICT (role_id, permission_alias) DO NOTHING;" ``` **See also:** [Web RBAC API][Web RBAC API]