From 2e0bceec51d892d74b1a6b762eb206fd037f27ed Mon Sep 17 00:00:00 2001 From: Ian Maddaus Date: Mon, 10 Mar 2025 14:37:51 -0400 Subject: [PATCH 1/6] Add 360 SaaS docs Signed-off-by: Ian Maddaus --- _vendor/github.com/chef/samples/LICENSE | 201 ++++++++++++ _vendor/github.com/chef/samples/README.md | 2 + .../chef/samples/cohorts/create-cohort.json | 6 + .../cohorts/node-override-setting.json | 103 +++++++ .../chef/samples/cohorts/skill-assembly.json | 53 ++++ .../00_empty-job-template.json | 89 ++++++ .../00_empty-job-template.yaml | 64 ++++ .../01_job-with-minimum-details.json | 52 ++++ .../01_job-with-minimum-details.yaml | 45 +++ .../create-job-simple.json | 76 +++++ .../create-job-simple.yaml | 66 ++++ .../infra_client_local.json | 64 ++++ .../infra_client_local.yaml | 51 +++ .../infra_client_pem_key_rotation.json | 62 ++++ .../infra_client_pem_key_rotation.yaml | 49 +++ .../infra_client_run.json | 59 ++++ .../infra_client_run.yaml | 47 +++ .../courier-job-examples/inspec_exec.json | 113 +++++++ .../courier-job-examples/inspec_exec.yaml | 85 +++++ .../inspec_with_token.json | 76 +++++ .../inspec_with_token.yaml | 54 ++++ .../job_direct_query_linux.json | 66 ++++ .../job_direct_query_linux.yaml | 57 ++++ .../courier-job-examples/job_reboot.json | 125 ++++++++ .../courier-job-examples/job_reboot.yaml | 98 ++++++ .../job_saved_filter_linux.json | 60 ++++ .../job_saved_filter_linux.yaml | 49 +++ .../job_saved_list_linux.json | 60 ++++ .../job_saved_list_linux.yaml | 49 +++ .../job_windows_conditional_actions.json | 186 +++++++++++ .../job_windows_conditional_actions.yaml | 140 +++++++++ .../macos-job-example.json | 138 +++++++++ .../macos-job-example.yaml | 121 ++++++++ ...roup-job-immediate-sequential-batched.json | 81 +++++ ...roup-job-immediate-sequential-batched.yaml | 69 +++++ ...ode-one-group-immediate-rolling-linux.json | 65 ++++ ...ode-one-group-immediate-rolling-linux.yaml | 49 +++ ...e-two-groups-immediate-parallel-linux.json | 76 +++++ ...e-two-groups-immediate-parallel-linux.yaml | 66 ++++ .../nginx_install_linux.json | 222 +++++++++++++ .../nginx_install_linux.yaml | 169 ++++++++++ .../courier-job-examples/nginx_patch.json | 154 +++++++++ .../courier-job-examples/nginx_patch.yaml | 123 ++++++++ .../nodeman-query-immediate-linux.json | 85 +++++ .../nodeman-saved-list-immediate.json | 60 ++++ .../nodeman-saved-list-immediate.yaml | 49 +++ .../nodeman-saved-query-immediate-linux.json | 60 ++++ .../nodeman-saved-query-immediate-linux.yaml | 49 +++ .../single-node-job-future-linux.json | 60 ++++ .../single-node-job-future-linux.yaml | 50 +++ ...single-node-job-reoccurring-exception.json | 65 ++++ ...single-node-job-reoccurring-exception.yaml | 52 ++++ .../ssl_cert_rotation.json | 185 +++++++++++ .../ssl_cert_rotation.yaml | 147 +++++++++ .../skills/chef-client-interpreter.json | 9 + .../samples/skills/courier-runner-skill.json | 17 + .../chef/samples/skills/gohai-skill.json | 17 + .../skills/inspec-interpreter-skill.json | 9 + .../skills/restart-interpreter-skill.json | 9 + .../skills/shell-interpreter-skill.json | 9 + _vendor/modules.txt | 1 + config/_default/menu.toml | 25 +- config/_default/module.toml | 13 + config/_default/params.toml | 2 +- content/360/saas/_index.md | 38 +++ content/360/saas/get_started/_index.md | 37 +++ .../saas/get_started/create_skill_assembly.md | 33 ++ content/360/saas/get_started/define_skills.md | 131 ++++++++ content/360/saas/get_started/enroll_nodes.md | 216 +++++++++++++ content/360/saas/get_started/install_cli.md | 164 ++++++++++ content/360/saas/get_started/jobs.md | 291 ++++++++++++++++++ content/360/saas/get_started/node_cohort.md | 58 ++++ .../360/saas/get_started/override_settings.md | 55 ++++ .../saas/get_started/register_node_agent.md | 61 ++++ content/360/saas/get_started/set_up.md | 58 ++++ .../saas/get_started/system_requirements.md | 58 ++++ content/360/saas/reusable_text/index.md | 11 + .../json/enroll-node-linux-rsa.json | 9 + .../json/enroll-node-windows.json | 8 + .../saas/reusable_text/md/clis_add_license.md | 12 + .../reusable_text/md/clis_install_saas.md | 20 ++ .../reusable_text/md/clis_verify_profiles.md | 42 +++ .../md/install_bash_completion.md | 51 +++ .../reusable_text/md/node_cohort_overview.md | 3 + .../md/node_enrollment_status_node_id.md | 23 ++ .../md/skill_assembly_get_started.md | 23 ++ content/saas/_index.md | 6 +- content/saas/get_started.md | 6 +- content/saas/opsworks_migration.md | 6 +- content/saas/register_nodes.md | 6 +- content/saas/sso.md | 6 +- go.mod | 1 + go.sum | 2 + static/images/360/select-role.png | Bin 0 -> 78538 bytes static/images/360/setting-expiry-token.png | Bin 0 -> 84341 bytes 95 files changed, 6027 insertions(+), 21 deletions(-) create mode 100644 _vendor/github.com/chef/samples/LICENSE create mode 100644 _vendor/github.com/chef/samples/README.md create mode 100644 _vendor/github.com/chef/samples/cohorts/create-cohort.json create mode 100644 _vendor/github.com/chef/samples/cohorts/node-override-setting.json create mode 100644 _vendor/github.com/chef/samples/cohorts/skill-assembly.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/create-job-simple.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/create-job-simple.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/infra_client_local.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/infra_client_local.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/infra_client_run.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/infra_client_run.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/inspec_exec.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/inspec_exec.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_reboot.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_reboot.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/macos-job-example.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/macos-job-example.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nginx_patch.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nginx_patch.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nodeman-query-immediate-linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.yaml create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.json create mode 100644 _vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.yaml create mode 100644 _vendor/github.com/chef/samples/skills/chef-client-interpreter.json create mode 100644 _vendor/github.com/chef/samples/skills/courier-runner-skill.json create mode 100644 _vendor/github.com/chef/samples/skills/gohai-skill.json create mode 100644 _vendor/github.com/chef/samples/skills/inspec-interpreter-skill.json create mode 100644 _vendor/github.com/chef/samples/skills/restart-interpreter-skill.json create mode 100644 _vendor/github.com/chef/samples/skills/shell-interpreter-skill.json create mode 100644 content/360/saas/_index.md create mode 100644 content/360/saas/get_started/_index.md create mode 100644 content/360/saas/get_started/create_skill_assembly.md create mode 100644 content/360/saas/get_started/define_skills.md create mode 100644 content/360/saas/get_started/enroll_nodes.md create mode 100644 content/360/saas/get_started/install_cli.md create mode 100644 content/360/saas/get_started/jobs.md create mode 100644 content/360/saas/get_started/node_cohort.md create mode 100644 content/360/saas/get_started/override_settings.md create mode 100644 content/360/saas/get_started/register_node_agent.md create mode 100644 content/360/saas/get_started/set_up.md create mode 100644 content/360/saas/get_started/system_requirements.md create mode 100644 content/360/saas/reusable_text/index.md create mode 100644 content/360/saas/reusable_text/json/enroll-node-linux-rsa.json create mode 100644 content/360/saas/reusable_text/json/enroll-node-windows.json create mode 100644 content/360/saas/reusable_text/md/clis_add_license.md create mode 100644 content/360/saas/reusable_text/md/clis_install_saas.md create mode 100644 content/360/saas/reusable_text/md/clis_verify_profiles.md create mode 100644 content/360/saas/reusable_text/md/install_bash_completion.md create mode 100644 content/360/saas/reusable_text/md/node_cohort_overview.md create mode 100644 content/360/saas/reusable_text/md/node_enrollment_status_node_id.md create mode 100644 content/360/saas/reusable_text/md/skill_assembly_get_started.md create mode 100644 static/images/360/select-role.png create mode 100644 static/images/360/setting-expiry-token.png diff --git a/_vendor/github.com/chef/samples/LICENSE b/_vendor/github.com/chef/samples/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/_vendor/github.com/chef/samples/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/_vendor/github.com/chef/samples/README.md b/_vendor/github.com/chef/samples/README.md new file mode 100644 index 0000000000..a3fbff376d --- /dev/null +++ b/_vendor/github.com/chef/samples/README.md @@ -0,0 +1,2 @@ +# samples +Open repo for sample content related to active Chef products such as cookbooks, policies, and job definitions, versioned with corresponding product version diff --git a/_vendor/github.com/chef/samples/cohorts/create-cohort.json b/_vendor/github.com/chef/samples/cohorts/create-cohort.json new file mode 100644 index 0000000000..fba36a7f8d --- /dev/null +++ b/_vendor/github.com/chef/samples/cohorts/create-cohort.json @@ -0,0 +1,6 @@ +{ + "name": "", + "description": "", + "settingId": "", + "skillAssemblyId": "" +} diff --git a/_vendor/github.com/chef/samples/cohorts/node-override-setting.json b/_vendor/github.com/chef/samples/cohorts/node-override-setting.json new file mode 100644 index 0000000000..7e6c8b89f5 --- /dev/null +++ b/_vendor/github.com/chef/samples/cohorts/node-override-setting.json @@ -0,0 +1,103 @@ +{ + "name":"sample-node-setting", + "skills":[ + { + "skillName":"chef-gohai", + "settings":[ + { + "name":"log_level", + "value":"debug" + }, + { + "name":"log_file_path", + "value":"/hab/svc/chef-gohai/logs/logs.log" + }, + { + "name":"log_to_file", + "value": true + }, + { + "name":"log_to_stdout", + "value": false + } + ] + }, + { + "skillName":"courier-runner", + "settings":[ + { + "name":"credentials_api_key", + "value":"" + }, + { + "name":"credentials_api_secret", + "value":"" + }, + { + "name":"shell_interpreter", + "value":"chef-platform/shell-interpreter" + }, + { + "name":"restart_interpreter", + "value":"chef-platform/restart-interpreter" + }, + { + "name":"inspec_interpreter", + "value":"chef-platform/inspec-interpreter" + }, + { + "name":"chef_client_interpreter", + "value":"chef-platform/chef-client-interpreter" + }, + { + "name":"log_dir", + "value":"/hab/svc/courier-runner/logs" + }, + { + "name":"log_format", + "value":"json" + }, + { + "name":"log_level", + "value":"debug" + }, + { + "name":"log_output", + "value":"file" + }, + { + "name":"queue_provider", + "value":"0" + }, + { + "name":"reporter_authentication_type", + "value":"basic" + }, + { + "name":"reporter_dir", + "value":"/hab/svc/courier-runner/data" + }, + { + "name":"reporter_host_url", + "value":"" + }, + { + "name":"reporter_interval_in_sec", + "value":"3" + }, + { + "name":"reporter_name", + "value":"server" + }, + { + "name":"reporter_retry_interval_in_sec", + "value":"4" + }, + { + "name":"reporter_total_retry_duration_in_min", + "value":"2" + } + ] + } + ] +} diff --git a/_vendor/github.com/chef/samples/cohorts/skill-assembly.json b/_vendor/github.com/chef/samples/cohorts/skill-assembly.json new file mode 100644 index 0000000000..3579f5592d --- /dev/null +++ b/_vendor/github.com/chef/samples/cohorts/skill-assembly.json @@ -0,0 +1,53 @@ +{ + "name": "my-skill-assembly", + "skills": [ + { + "action": "add", + "skill": { + "name": "courier-runner", + "channel": "stable", + "value": ["1.4.6"] + } + }, + { + "action": "add", + "skill": { + "channel": "stable", + "name": "chef-gohai", + "value": ["1.2.1"] + } + }, + { + "action": "add", + "skill": { + "name": "shell-interpreter", + "channel": "stable", + "value": ["1.0.5"] + } + }, + { + "action": "add", + "skill": { + "name": "inspec-interpreter", + "channel": "stable", + "value": ["1.0.6"] + } + }, + { + "action": "add", + "skill": { + "name": "restart-interpreter", + "channel": "stable", + "value": ["1.0.4"] + } + }, + { + "action": "add", + "skill": { + "name": "chef-client-interpreter", + "channel": "stable", + "value": ["1.0.6"] + } + } + ] +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.json b/_vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.json new file mode 100644 index 0000000000..027fd8a80c --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.json @@ -0,0 +1,89 @@ +{ + "name":"", + "description": "", + "scheduleRule": "immediate|RRule", + "exceptionRules": [], + "target": { + "executionType": "sequential"|"parallel", + "groups":[ + { + "timeoutSeconds": , + "batchSize": { + "type": "number"|"percent", + "value": + }, + "distributionMethod": "rolling"|"batching", + "successCriteria": [ + { + "numRuns": { + "type": "number"|"percent", + "value": + }, + "status": "success"|"failure" + } + ], + "nodeListType": "filter"|"savedFilter"|"savedList"|"nodes", + "listId": "", + "filterId": , + "nodeIdentifiers":[""], + "filter": {} + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": + [ + { + "name": "", + "description": "", + "command": {}, + "inputs": {}, + "interpreter": { + "skill": { + "minVersion": "", + "maxVersion": "" + }, + "name": "" + }, + "expectedInputs": { + "": { + "default": "", + "required": , + "sensitive": + } + }, + "outputFieldRules": { + "sourceType": "artifact"|"exitCode"|"file"|"output", + "source": "", + "extractMethod": "regex"|"jsonPath"|"content", + "expression": "", + "required": , + "sensitive": + }, + "retryCount": , + "failureBehavior": { + "action": "retryThenFail"|"retryThenIgnore", + "retryBackoffStrategy": { + "name": "none"|"linear"|"exponential"|"polynomial", + "delaySeconds": , + "arguments": [] + } + }, + "limits": { + "cores": , + "cpu": , + "timeoutSeconds": , + }, + "conditions": [ + { + "inputName": "", + "negate": , + "operator": "eq"|"gt"|"gte"|"lt"|"lte"|"matches"|"startsWith"|"endsWith"|"contains", + "value": "" + } + ] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.yaml b/_vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.yaml new file mode 100644 index 0000000000..e28fccbaf3 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/00_empty-job-template.yaml @@ -0,0 +1,64 @@ +--- +name: +description: +scheduleRule: immediate|RRule +exceptionRules: [] +target: + executionType: sequential|parallel + groups: + - timeoutSeconds: + batchSize: + type: number|percent + value: + distributionMethod: rolling|batching + successCriteria: + - numRuns: + type: number|percent + value: + status: success|failure + nodeListType: filter|savedFilter|savedList|nodes + listId: + filterId: + nodeIdentifiers: + - + filter: {} +actions: + accessMode: agent + steps: + - name: + description: + command: {} + inputs: {} + interpreter: + skill: + minVersion: '' + maxVersion: '' + name: '' + expectedInputs: + : + default: + required: + sensitive: + outputFieldRules: + sourceType: artifact|exitCode|file|output + source: + extractMethod: regex|jsonPath|content + expression: + required: + sensitive: + retryCount: + failureBehavior: + action: retryThenFail|retryThenIgnore + retryBackoffStrategy: + name: none|linear|exponential|polynomial + delaySeconds: + arguments: [] + limits: + cores: + cpu: + timeoutSeconds: + conditions: + - inputName: + negate: + operator: eq|gt|gte|lt|lte|matches|startsWith|endsWith|contains + value: diff --git a/_vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.json b/_vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.json new file mode 100644 index 0000000000..4efe6e7824 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.json @@ -0,0 +1,52 @@ +{ + "name": "", + "description": "", + "exceptionRules":[], + "scheduleRule":"", + "target": { + "executionType": "", + "groups":[ + { + "timeoutSeconds": , + "batchSize": { + "type":"", + "value": + }, + "distributionMethod":"", + "successCriteria": [{"status":"", "numRuns":{"type":"", "value":}}], + "nodeListType": "", + "listId": "", + "filterId": , + "nodeIdentifiers":[""], + "filter": {} + } + ] + }, + "actions": { + "accessMode":"agent", + "steps": + [ + { + "name": "", + "interpreter": { + "name": "", + "skill": { + "minVersion": "", + "maxVersion": "" + } + }, + "command": {}, + "inputs":{}, + "expectedInputs":{}, + "outputFieldRules":{}, + "retryCount": , + "limits":{}, + "conditions":[], + "failureBehavior":{ + "action":"retryThenFail", + "retryBackoffStrategy":{"name":"none", "delaySeconds":} + } + } + ] + } +} \ No newline at end of file diff --git a/_vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.yaml b/_vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.yaml new file mode 100644 index 0000000000..55e185d57b --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/01_job-with-minimum-details.yaml @@ -0,0 +1,45 @@ +--- +name: "" +description: "" +exceptionRules: [] +scheduleRule: "" +target: + executionType: "" + groups: + - timeoutSeconds: + batchSize: + type: "" + value: + distributionMethod: "" + successCriteria: + - status: "" + numRuns: + type: "" + value: + nodeListType: "" + listId: "" + filterId: + nodeIdentifiers: + - "" + filter: {} +actions: + accessMode: agent + steps: + - name: "" + interpreter: + name: "" + skill: + minVersion: "" + maxVersion: "" + command: {} + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: + limits: {} + conditions: [] + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + name: none + delaySeconds: diff --git a/_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.json b/_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.json new file mode 100644 index 0000000000..947cfe34d3 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.json @@ -0,0 +1,76 @@ +{ + "name": "a simple job to perform one action", + "description": "Perform a simple shell command on specific nodes to understand the fundamentals of Courier jobs", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 240, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + }, + { + "timeoutSeconds": 120, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE2--", "--NODE3--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.yaml b/_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.yaml new file mode 100644 index 0000000000..35e3972a84 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.yaml @@ -0,0 +1,66 @@ +--- +name: a simple job to perform one action +description: + Perform a simple shell command on specific nodes to understand the fundamentals + of Courier jobs +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 240 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" + - timeoutSeconds: 120 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE2--" + - "--NODE3--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/infra_client_local.json b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_local.json new file mode 100644 index 0000000000..bd42221a42 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_local.json @@ -0,0 +1,64 @@ +{ + "name": "infra client local run", + "description": "Perform simple Chef Infra Client run from local using courier jobs", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 240, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to pem keys", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "20.9.99" + }, + "name": "chef-platform/chef-client-interpreter" + }, + "command": { + "exec": "run", + "args": { + "mode": "local", + "path": "/home/ec2-user/chef-repo/cookbooks", + "runlist": "nginx::default" + } + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/infra_client_local.yaml b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_local.yaml new file mode 100644 index 0000000000..f54ed4b8c5 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_local.yaml @@ -0,0 +1,51 @@ +--- +name: infra client local run +description: Perform simple Chef Infra Client run from local using courier jobs +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 240 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to pem keys + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 20.9.99 + name: chef-platform/chef-client-interpreter + command: + exec: run + args: + mode: local + path: "/home/ec2-user/chef-repo/cookbooks" + runlist: nginx::default + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.json b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.json new file mode 100644 index 0000000000..a032993bc0 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.json @@ -0,0 +1,62 @@ +{ + "name": "a simple job to showcase invoking Chef Infra Client", + "description": "Perform simple Chef Infra Client actions using courier jobs", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 240, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to pem keys", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "19.9.99" + }, + "name": "chef-platform/chef-client-interpreter" + }, + "command": { + "exec": "rotate credentials", + "args": { + "config": "/home/ubuntu/.chef/credentials" + } + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.yaml b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.yaml new file mode 100644 index 0000000000..a79bc1e9d6 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_pem_key_rotation.yaml @@ -0,0 +1,49 @@ +--- +name: a simple job to showcase invoking Chef Infra Client +description: Perform simple Chef Infra Client actions using courier jobs +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 240 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to pem keys + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 20.9.99 + name: chef-platform/chef-client-interpreter + command: + exec: rotate credentials + args: + config: "/etc/chef/client.pem" + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/infra_client_run.json b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_run.json new file mode 100644 index 0000000000..96a6cb37da --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_run.json @@ -0,0 +1,59 @@ +{ + "name": "infra client remote run", + "description": "Perform simple Chef Infra Client run using courier jobs", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 240, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to pem keys", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "20.9.99" + }, + "name": "chef-platform/chef-client-interpreter" + }, + "command": { + "exec": "run" + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/infra_client_run.yaml b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_run.yaml new file mode 100644 index 0000000000..d2ff525f16 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/infra_client_run.yaml @@ -0,0 +1,47 @@ +--- +name: infra client remote run +description: Perform simple Chef Infra Client run using courier jobs +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 240 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to pem keys + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 20.9.99 + name: chef-platform/chef-client-interpreter + command: + exec: run + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/inspec_exec.json b/_vendor/github.com/chef/samples/courier-job-examples/inspec_exec.json new file mode 100644 index 0000000000..c84d7c25f0 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/inspec_exec.json @@ -0,0 +1,113 @@ +{ + "name": "Inspec scan", + "description": "Example to showcase running an Inspec exec on Linux", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 120, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { + "type": "percent", + "value": 100 + }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "20.0.6" + }, + "name": "chef-platform/inspec-interpreter" + }, + + "command": { + "exec": "scan", + "args": { + "path": "https://github.com/akshayparvatikar29/cert-compliance" + } + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "INSPEC_VALUE": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "regEx", + "expression": "0 successful", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [], + "name": "capture inspec value into variable" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "20.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "INSPEC_VALUE": { + "type": "string", + "sensitive": false, + "required": true, + "default": "" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "INSPEC_VALUE", + "operator": "eq", + "value": "0 successful" + } + ], + "command": { "linux": ["sleep 10"] }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "executing command with inspec variable" + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/inspec_exec.yaml b/_vendor/github.com/chef/samples/courier-job-examples/inspec_exec.yaml new file mode 100644 index 0000000000..979a849958 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/inspec_exec.yaml @@ -0,0 +1,85 @@ +--- +name: Inspec scan +description: Example to showcase running an Inspec exec on Linux +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 120 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: capture inspec value into variable + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 16.0.0 + name: chef-platform/inspec-interpreter + command: + exec: scan + args: + path: https://github.com/akshayparvatikar29/cert-compliance + inputs: {} + expectedInputs: {} + outputFieldRules: + INSPEC_VALUE: + source: stdout + sourceType: output + extractMethod: regEx + expression: 0 successful + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: + INSPEC_VALUE: + type: string + sensitive: false + required: true + default: "" + outputFieldRules: {} + conditions: + - inputName: INSPEC_VALUE + operator: eq + value: 0 successful + command: + linux: + - sleep 10 + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: executing command with inspec variable diff --git a/_vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.json b/_vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.json new file mode 100644 index 0000000000..4696ad303b --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.json @@ -0,0 +1,76 @@ +{ + "name":"Inspec exec with automate token", + "description":"Example to showcase running an Inspec exec by connecting with Chef Automate using a token", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 120, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { + "type": "percent", + "value": 100 + }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": [ + "--NODE1--" + ] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + + "name": "inspec", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "20.0.0" + }, + "name": "chef-platform/inspec-interpreter" + }, + "command":{ + "exec":"scan", + "args":{ + "username": "", + "path": "admin/ssh-baseline", + "token": "xxxxxxxxxxxx", + "sourceURL": "", + "source": "automate" + } + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [ + 1, + 3, + 5 + ] + } + }, + "limits": {}, + "conditions": [] + } + ] + } + } \ No newline at end of file diff --git a/_vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.yaml b/_vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.yaml new file mode 100644 index 0000000000..cbbf3671cf --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/inspec_with_token.yaml @@ -0,0 +1,54 @@ +--- +name: Inspec exec with automate token +description: Example to showcase running an Inspec exec by connecting with Chef Automate + using a token +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 120 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: inspec + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 20.0.0 + name: chef-platform/inspec-interpreter + command: + exec: scan + args: + username: "" + path: admin/ssh-baseline + token: xxxxxxxxxxxx + sourceURL: "" + source: automate + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.json b/_vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.json new file mode 100644 index 0000000000..1725643660 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.json @@ -0,0 +1,66 @@ +{ + "name": "job direct query", + "description": "Demonstrating a simple job to be performed against nodes resolved for an adhoc search query for Linux in batches of 5 nodes", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 60, + "batchSize": { + "type": "number", + "value": 5 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "filter", + "filter": { + "constraints": { + "attributes": [ + { "name": "kernel_name", "operator": "=", "value": ["Linux"] } + ] + } + } + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.yaml new file mode 100644 index 0000000000..7c3138b9cb --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_direct_query_linux.yaml @@ -0,0 +1,57 @@ +--- +name: job direct query +description: + Demonstrating a simple job to be performed against nodes resolved for + an adhoc search query for Linux in batches of 5 nodes +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 60 + batchSize: + type: number + value: 5 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: filter + filter: + constraints: + attributes: + - name: kernel_name + operator: "=" + value: + - Linux +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_reboot.json b/_vendor/github.com/chef/samples/courier-job-examples/job_reboot.json new file mode 100644 index 0000000000..1889cd2931 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_reboot.json @@ -0,0 +1,125 @@ +{ + "name": "Sample reboot", + "description": "To demonstrate a reboot action as a part of a simple courier job on a node", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 240, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to perform file write before a reboot", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": [ + "echo 'before restart..' > /home/ec2-user/before-restart.txt" + ], + "windows": [ + "echo 'before restart..' > C:\\Users\\Administrator\\before-restart.txt" + ] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + }, + { + "name": "step to perform reboot", + "interpreter": { + "skill": { + "minVersion": "0.0.0", + "maxVersion": "2.0.0" + }, + "name": "chef-platform/restart-interpreter" + }, + "command": { + "exec": "machine_reboot" + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + }, + { + "name": "step to perform file write after reboot", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": [ + "echo 'after restart..' > /home/ec2-user/after-restart.txt" + ], + "windows": [ + "echo 'after restart..' > C:\\Users\\Administrator\\after-restart.txt" + ] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "required": false + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_reboot.yaml b/_vendor/github.com/chef/samples/courier-job-examples/job_reboot.yaml new file mode 100644 index 0000000000..6e4dc2e48f --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_reboot.yaml @@ -0,0 +1,98 @@ +--- +name: Sample reboot +description: To demonstrate a reboot action as a part of a simple courier job on a + node +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 240 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to perform file write before a reboot + interpreter: + skill: + minVersion: 1.0.0 + name: chef-platform/shell-interpreter + command: + linux: + - echo 'before restart..' > /home/ec2-user/before-restart.txt + windows: + - echo 'before restart..' > C:\Users\Administrator\before-restart.txt + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + - name: step to perform reboot + interpreter: + skill: + minVersion: 0.0.0 + maxVersion: 2.0.0 + name: chef-platform/restart-interpreter + command: + exec: machine_reboot + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + - name: step to perform file write after reboot + interpreter: + skill: + minVersion: 1.0.0 + name: chef-platform/shell-interpreter + command: + linux: + - echo 'after restart..' > /home/ec2-user/after-restart.txt + windows: + - echo 'after restart..' > C:\Users\Administrator\after-restart.txt + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.json b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.json new file mode 100644 index 0000000000..1254eea7d3 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.json @@ -0,0 +1,60 @@ +{ + "name": "job saved filter", + "description": "demonstrating running a job using a saved filter", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 300, + "batchSize": { + "type": "number", + "value": 5 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "savedFilter", + "filterId": "--FILTER ID--" + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.yaml new file mode 100644 index 0000000000..14547bbd5d --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_filter_linux.yaml @@ -0,0 +1,49 @@ +--- +name: job saved filter +description: demonstrating running a job using a saved filter +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 300 + batchSize: + type: number + value: 5 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: savedFilter + filterId: "--FILTER ID--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.json b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.json new file mode 100644 index 0000000000..b2e10113d5 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.json @@ -0,0 +1,60 @@ +{ + "name": "job saved list", + "description": "demonstrating running a job using a saved node list", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 60, + "batchSize": { + "type": "number", + "value": 5 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "savedList", + "listId": "--LIST ID--" + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.yaml new file mode 100644 index 0000000000..39c836f247 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_saved_list_linux.yaml @@ -0,0 +1,49 @@ +--- +name: job saved list +description: demonstrating running a job using a saved node list +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 60 + batchSize: + type: number + value: 5 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: savedList + listId: "--LIST ID--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.json b/_vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.json new file mode 100644 index 0000000000..09f863e7c2 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.json @@ -0,0 +1,186 @@ +{ + "name": "Windows conditional actions", + "description": "A job to simulate how courier can execute steps conditionally based on a response", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 160, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "rolling", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "windows": ["echo 'Adding value2 sample'"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "CAN_PERFORM_TASK": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "regEx", + "expression": "value2", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "conditions": [], + "name": "step to simulate a value being received" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "outputFieldRules": {}, + "expectedInputs": { + "CAN_PERFORM_TASK": { + "type": "string", + "sensitive": false, + "required": true, + "default": "true" + } + }, + "conditions": [ + { + "inputName": "CAN_PERFORM_TASK", + "operator": "eq", + "value": "value2" + } + ], + "command": { + "windows": [ + "echo {{.CAN_PERFORM_TASK}} > C:\\Users\\Administrator\\task.txt" + ] + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "step to simulate conditionally performing a command based on previous step" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "windows": ["cat C:\\Users\\Administrator\\task.txt"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "TASK_COMPLETED": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "content", + "expression": "", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "conditions": [], + "limits": {}, + "name": "step to check if the previous command ran conditionally" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "TASK_COMPLETED": { + "type": "string", + "sensitive": false, + "required": true, + "default": "true" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "TASK_COMPLETED", + "operator": "eq", + "value": "value2\r\n" + } + ], + "command": { + "windows": ["timeout 1"] + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "step to output if a task was completed" + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.yaml b/_vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.yaml new file mode 100644 index 0000000000..a493b9808f --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/job_windows_conditional_actions.yaml @@ -0,0 +1,140 @@ +--- +name: Windows conditional actions +description: + A job to simulate how courier can execute steps conditionally based on + a response +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 160 + batchSize: + type: number + value: 1 + distributionMethod: rolling + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + windows: + - echo 'Adding value2 sample' + inputs: {} + expectedInputs: {} + outputFieldRules: + CAN_PERFORM_TASK: + source: stdout + sourceType: output + extractMethod: regEx + expression: value2 + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + conditions: [] + name: step to simulate a value being received + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + outputFieldRules: {} + expectedInputs: + CAN_PERFORM_TASK: + type: string + sensitive: false + required: true + default: "true" + conditions: + - inputName: CAN_PERFORM_TASK + operator: eq + value: value2 + command: + windows: + - echo {{.CAN_PERFORM_TASK}} > C:\Users\Administrator\task.txt + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: step to simulate conditionally performing a command based on previous step + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + windows: + - cat C:\Users\Administrator\task.txt + inputs: {} + expectedInputs: {} + outputFieldRules: + TASK_COMPLETED: + source: stdout + sourceType: output + extractMethod: content + expression: "" + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + conditions: [] + limits: {} + name: step to check if the previous command ran conditionally + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: + TASK_COMPLETED: + type: string + sensitive: false + required: true + default: "true" + outputFieldRules: {} + conditions: + - inputName: TASK_COMPLETED + operator: eq + value: "value2\r\n" + command: + windows: + - timeout 1 + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: step to output if a task was completed diff --git a/_vendor/github.com/chef/samples/courier-job-examples/macos-job-example.json b/_vendor/github.com/chef/samples/courier-job-examples/macos-job-example.json new file mode 100644 index 0000000000..367c585df1 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/macos-job-example.json @@ -0,0 +1,138 @@ +{ + "name": "shell command with mac OS", + "description": "To demonstrate a reboot action as a part of a simple courier job on multiple operating systems", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 240, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to check last reboot time windows and linux", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["last reboot"], + "darwin": ["last reboot"], + "windows": ["wmic os get lastbootuptime"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "last_reboot_time": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "content", + "expression": "false", + "required": true, + "sensitive": false + } + }, + "retryCount": 1, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + }, + { + "name": "step to reboot machine", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/restart-interpreter" + }, + "command": { + "exec": "machine_reboot", + "args": { + "time": "now" + } + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 1, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + }, + { + "name": "step to check last reboot time windows and linux after restart", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["last reboot"], + "darwin": ["last reboot"], + "windows": ["wmic os get lastbootuptime"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "new_reboot_time": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "content", + "expression": "false", + "required": true, + "sensitive": false + } + }, + "retryCount": 1, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/macos-job-example.yaml b/_vendor/github.com/chef/samples/courier-job-examples/macos-job-example.yaml new file mode 100644 index 0000000000..62708e659a --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/macos-job-example.yaml @@ -0,0 +1,121 @@ +--- +name: shell command with mac OS +description: + To demonstrate a reboot action as a part of a simple courier job on multiple + operating systems +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 240 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to check last reboot time windows and linux + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - last reboot + darwin: + - last reboot + windows: + - wmic os get lastbootuptime + inputs: {} + expectedInputs: {} + outputFieldRules: + last_reboot_time: + source: stdout + sourceType: output + extractMethod: content + expression: "false" + required: true + sensitive: false + retryCount: 1 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + - name: step to reboot machine + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/restart-interpreter + command: + exec: machine_reboot + args: + time: 200 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 1 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + - name: step to check last reboot time windows and linux after restart + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - last reboot + darwin: + - last reboot + windows: + - wmic os get lastbootuptime + inputs: {} + expectedInputs: {} + outputFieldRules: + new_reboot_time: + source: stdout + sourceType: output + extractMethod: content + expression: "false" + required: true + sensitive: false + retryCount: 1 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.json b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.json new file mode 100644 index 0000000000..b8ed1ceb54 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.json @@ -0,0 +1,81 @@ +{ + "name": "multi-node-multi-group-job-batching", + "description": "demonstrating an immediate job executing sequential on multiple nodes with batched rollout", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 300, + "batchSize": { + "type": "number", + "value": 2 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": [ + "--NODE1--", + "--NODE2--", + "--NODE3--", + "--NODE4--", + "--NODE5--" + ] + }, + { + "timeoutSeconds": 300, + "batchSize": { + "type": "number", + "value": 2 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE6--", "--NODE7--", "--NODE8--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep for a random period", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep $((RANDOM % 120))"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 1, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.yaml b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.yaml new file mode 100644 index 0000000000..348d8b9164 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-multi-group-job-immediate-sequential-batched.yaml @@ -0,0 +1,69 @@ +--- +name: multi-node-multi-group-job-batching +description: + demonstrating an immediate job executing sequential on multiple nodes + with batched rollout +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 300 + batchSize: + type: number + value: 2 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" + - "--NODE2--" + - "--NODE3--" + - "--NODE4--" + - "--NODE5--" + - timeoutSeconds: 300 + batchSize: + type: number + value: 2 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE6--" + - "--NODE7--" + - "--NODE8--" +actions: + accessMode: agent + steps: + - name: step to sleep for a random period + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep $((RANDOM % 120)) + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 1 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.json b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.json new file mode 100644 index 0000000000..4069685570 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.json @@ -0,0 +1,65 @@ +{ + "name": "multi-node-one-group-immediate-rolling", + "description": "demonstrating a immediate job executing sequential on batches of percentage", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 300, + "batchSize": { + "type": "percent", + "value": 20 + }, + "distributionMethod": "rolling", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": [ + "--NODE1--", + "--NODE2--", + "--NODE3--", + "--NODE4--", + "--NODE5--" + ] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep for a random period", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep $((RANDOM % 120))"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 1, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.yaml new file mode 100644 index 0000000000..8b92e37458 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-one-group-immediate-rolling-linux.yaml @@ -0,0 +1,49 @@ +--- +name: multi-node-one-group-immediate-rolling +description: demonstrating a immediate job executing sequential on batches of percentage +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 300 + batchSize: + type: percent + value: 20 + distributionMethod: rolling + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" + - "--NODE2--" + - "--NODE3--" + - "--NODE4--" + - "--NODE5--" +actions: + accessMode: agent + steps: + - name: step to sleep for a random period + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep $((RANDOM % 120)) + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 1 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: [] + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.json b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.json new file mode 100644 index 0000000000..b4679de37c --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.json @@ -0,0 +1,76 @@ +{ + "name": "multi-node-two-groups-immediate-parallel-linux", + "description": "demonstrating an immediate job executing parallel on multi nodes", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "parallel", + "groups": [ + { + "timeoutSeconds": 1500, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--", "--NODE2--"] + }, + { + "timeoutSeconds": 1500, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE3--", "--NODE4--", "--NODE5--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.yaml new file mode 100644 index 0000000000..dbbb860f6c --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/multi-node-two-groups-immediate-parallel-linux.yaml @@ -0,0 +1,66 @@ +--- +name: multi-node-two-groups-immediate-parallel-linux +description: demonstrating an immediate job executing parallel on multi nodes +scheduleRule: immediate +exceptionRules: [] +target: + executionType: parallel + groups: + - timeoutSeconds: 1500 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" + - "--NODE2--" + - timeoutSeconds: 1500 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE3--" + - "--NODE4--" + - "--NODE5--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.json b/_vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.json new file mode 100644 index 0000000000..7c6b93f211 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.json @@ -0,0 +1,222 @@ +{ + "name": "nginx-install", + "description": "A simple demonstration that shows a multi-step job that declares outputs and evaluates inputs to install or configure applications conditionally", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 160, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "rolling", + "successCriteria": [ + { + "numRuns": { + "type": "percent", + "value": 100 + }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["which nginx >/dev/null && echo true || echo false"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "NGINX_FOUND": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "content", + "expression": "", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "conditions": [], + "name": "a step to check nginx presence" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "NGINX_FOUND": { + "type": "string", + "sensitive": false, + "required": true, + "default": "" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "NGINX_FOUND", + "operator": "eq", + "value": "false\n" + } + ], + "command": { + "linux": [ + "yum install nginx -y 2>&1 >/dev/null", + "systemctl enable nginx 2>&1 >/dev/null", + "systemctl start nginx 2>&1 >/dev/null" + ] + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "install nginx conditionally" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": [ + "curl -s http://localhost:80 | grep 'hello world!' >/dev/null && echo true || echo false" + ] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "EXPECTED_PAGE_FOUND": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "content", + "expression": "", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "conditions": [], + "name": "check if nginx is configured" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "EXPECTED_PAGE_FOUND": { + "type": "string", + "sensitive": false, + "required": true, + "default": "" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "EXPECTED_PAGE_FOUND", + "operator": "eq", + "value": "false\n" + } + ], + "command": { + "linux": [ + "echo '

hello world!

' | sudo tee /usr/share/nginx/html/index.html > /dev/null" + ] + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "configure nginx if not already" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["curl -s http://localhost:80 | grep 'hello world!'"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "conditions": [], + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "check if nginx is properly configured" + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.yaml new file mode 100644 index 0000000000..564c837c12 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nginx_install_linux.yaml @@ -0,0 +1,169 @@ +--- +name: nginx-install +description: + A simple demonstration that shows a multi-step job that declares outputs + and evaluates inputs to install or configure applications conditionally +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 160 + batchSize: + type: number + value: 1 + distributionMethod: rolling + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - which nginx >/dev/null && echo true || echo false + inputs: {} + expectedInputs: {} + outputFieldRules: + NGINX_FOUND: + source: stdout + sourceType: output + extractMethod: content + expression: "" + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + conditions: [] + name: a step to check nginx presence + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: + NGINX_FOUND: + type: string + sensitive: false + required: true + default: "" + outputFieldRules: {} + conditions: + - inputName: NGINX_FOUND + operator: eq + value: "false + + " + command: + linux: + - yum install nginx -y 2>&1 >/dev/null + - systemctl enable nginx 2>&1 >/dev/null + - systemctl start nginx 2>&1 >/dev/null + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: install nginx conditionally + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - "curl -s http://localhost:80 | grep 'hello world!' >/dev/null && echo true + || echo false" + inputs: {} + expectedInputs: {} + outputFieldRules: + EXPECTED_PAGE_FOUND: + source: stdout + sourceType: output + extractMethod: content + expression: "" + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + conditions: [] + name: check if nginx is configured + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: + EXPECTED_PAGE_FOUND: + type: string + sensitive: false + required: true + default: "" + outputFieldRules: {} + conditions: + - inputName: EXPECTED_PAGE_FOUND + operator: eq + value: "false + + " + command: + linux: + - "echo '

hello world!

' | sudo tee /usr/share/nginx/html/index.html + > /dev/null" + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: configure nginx if not already + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - curl -s http://localhost:80 | grep 'hello world!' + inputs: {} + expectedInputs: {} + outputFieldRules: {} + conditions: [] + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: check if nginx is properly configured diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nginx_patch.json b/_vendor/github.com/chef/samples/courier-job-examples/nginx_patch.json new file mode 100644 index 0000000000..9318159f9b --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nginx_patch.json @@ -0,0 +1,154 @@ +{ + "name": "nginx-patch", + "description": "A simple demonstration to showcase patching an installed application", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 300, + "batchSize": { + "type": "number", + "value": 2 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { "linux": ["nginx -v 2>&1 >/dev/null"] }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "NGINX_FOUND": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "content", + "expression": "", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "conditions": [], + "name": "a step to check nginx presence" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "NGINX_FOUND": { + "type": "string", + "sensitive": false, + "required": true, + "default": "" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "NGINX_FOUND", + "operator": "eq", + "value": "nginx version: nginx/1.25.0\n" + } + ], + "command": { "linux": ["sleep 5"] }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "Sleep if nginx version is 1.25.0" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "NGINX_FOUND": { + "type": "string", + "sensitive": false, + "required": true, + "default": "" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "NGINX_FOUND", + "operator": "eq", + "value": "nginx version: nginx/1.23.4\n" + } + ], + "command": { + "linux": [ + "sudo apt-get remove nginx nginx-common -y", + "sudo apt-get purge nginx nginx-common -y", + "wget http://nginx.org/keys/nginx_signing.key 2>&1 >/dev/null", + "sudo apt-key add nginx_signing.key", + "sudo add-apt-repository \"deb http://nginx.org/packages/mainline/ubuntu/ $(lsb_release -sc) nginx\" 2>&1 >/dev/null", + "sudo apt-get update", + "sudo apt-get install nginx=1.25.0-1~$(lsb_release -sc) 2>&1 >/dev/null", + "sudo systemctl enable nginx", + "sudo systemctl start nginx" + ] + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [] + } + }, + "limits": {}, + "name": "Install nginx 1.25.0, if the version is 1.23.4" + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nginx_patch.yaml b/_vendor/github.com/chef/samples/courier-job-examples/nginx_patch.yaml new file mode 100644 index 0000000000..2b76a214f8 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nginx_patch.yaml @@ -0,0 +1,123 @@ +--- +name: nginx-patch +description: A simple demonstration to showcase patching an installed application +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 300 + batchSize: + type: number + value: 2 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - nginx -v 2>&1 >/dev/null + inputs: {} + expectedInputs: {} + outputFieldRules: + NGINX_FOUND: + source: stdout + sourceType: output + extractMethod: content + expression: "" + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + conditions: [] + name: a step to check nginx presence + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: + NGINX_FOUND: + type: string + sensitive: false + required: true + default: "" + outputFieldRules: {} + conditions: + - inputName: NGINX_FOUND + operator: eq + value: "nginx version: nginx/1.25.0 + + " + command: + linux: + - sleep 5 + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: Sleep if nginx version is 1.25.0 + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: + NGINX_FOUND: + type: string + sensitive: false + required: true + default: "" + outputFieldRules: {} + conditions: + - inputName: NGINX_FOUND + operator: eq + value: "nginx version: nginx/1.23.4 + + " + command: + linux: + - sudo apt-get remove nginx nginx-common -y + - sudo apt-get purge nginx nginx-common -y + - wget http://nginx.org/keys/nginx_signing.key 2>&1 >/dev/null + - sudo apt-key add nginx_signing.key + - sudo add-apt-repository "deb http://nginx.org/packages/mainline/ubuntu/ $(lsb_release + -sc) nginx" 2>&1 >/dev/null + - sudo apt-get update + - sudo apt-get install nginx=1.25.0-1~$(lsb_release -sc) 2>&1 >/dev/null + - sudo systemctl enable nginx + - sudo systemctl start nginx + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: [] + limits: {} + name: Install nginx 1.25.0, if the version is 1.23.4 diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nodeman-query-immediate-linux.json b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-query-immediate-linux.json new file mode 100644 index 0000000000..8ce2972f5e --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-query-immediate-linux.json @@ -0,0 +1,85 @@ +{ + "name": "nodeman-query-immediate-linux", + "description": "Demonstrating a courier job using an adhoc search query against different sample atttributes as target", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 3000, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "filter", + "filter": { + "constraints": { + "attributes": [ + { + "name": "kernel_name", + "operator": "=", + "value": ["Linux"] + }, + { + "name": "primary_ip", + "operator": "MATCHES", + "value": ["^172\\.31\\.29.*"] + } + ], + "skills": [ + { + "name": "courier-runner", + "version": ["<= 1.9.996"] + }, + { + "name": "chef-gohai", + "version": ["= 0.1.0"] + } + ] + } + } + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.json b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.json new file mode 100644 index 0000000000..7758bce15b --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.json @@ -0,0 +1,60 @@ +{ + "name": "nodeman-saved-list-immediate-linux", + "description": "demonstrating a courier job utilising a saved node list", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 3000, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "savedList", + "listId": "--LISTID1--" + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.yaml b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.yaml new file mode 100644 index 0000000000..a40ca3725d --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-list-immediate.yaml @@ -0,0 +1,49 @@ +--- +name: nodeman-saved-list-immediate-linux +description: demonstrating a courier job utilising a saved node list +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 3000 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: savedList + listId: "--LISTID1--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.json b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.json new file mode 100644 index 0000000000..7dd3c1e7e7 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.json @@ -0,0 +1,60 @@ +{ + "name": "nodeman-saved-filter-immediate-linux", + "description": "Demonstrating a courier job utlising a saved node filter", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 3000, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "savedFilter", + "filterId": "--FILTERID1--" + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.yaml new file mode 100644 index 0000000000..9561f02b75 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/nodeman-saved-query-immediate-linux.yaml @@ -0,0 +1,49 @@ +--- +name: nodeman-saved-filter-immediate-linux +description: Demonstrating a courier job utlising a saved node filter +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 3000 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: savedFilter + filterId: "--FILTERID1--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.json b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.json new file mode 100644 index 0000000000..bd21c2ad7a --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.json @@ -0,0 +1,60 @@ +{ + "name": "single-node-job-future-linux", + "description": "demonstrating a scheduled job executing on a specific day", + "scheduleRule": "RRULE:FREQ=MINUTELY;COUNT=2;WKST=MO", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 300, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.yaml b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.yaml new file mode 100644 index 0000000000..60650e4804 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-future-linux.yaml @@ -0,0 +1,50 @@ +--- +name: single-node-job-future-linux +description: demonstrating a scheduled job executing on a specific day +scheduleRule: RRULE:FREQ=MINUTELY;COUNT=2;WKST=MO +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 300 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.json b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.json new file mode 100644 index 0000000000..9bf5c93be4 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.json @@ -0,0 +1,65 @@ +{ + "name": "single-node-job-reoccurring-linux", + "description": "demonstrating a scheduled job that runs multiple times with exceptions", + "scheduleRule": "RRULE:FREQ=MINUTELY;COUNT=10", + "exceptionRules": [ + { + "rrule": "RRULE:FREQ=MINUTELY;INTERVAL=3", + "duration": 1 + } + ], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 300, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { "type": "percent", "value": 100 }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "name": "step to sleep", + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": ["sleep 10"], + "windows": ["timeout 10"] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [] + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.yaml b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.yaml new file mode 100644 index 0000000000..dea66fdcef --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/single-node-job-reoccurring-exception.yaml @@ -0,0 +1,52 @@ +--- +name: single-node-job-reoccurring-linux +description: demonstrating a scheduled job that runs multiple times with exceptions +scheduleRule: RRULE:FREQ=MINUTELY;COUNT=10 +exceptionRules: + - rrule: RRULE:FREQ=MINUTELY;INTERVAL=3 + duration: 1 +target: + executionType: sequential + groups: + - timeoutSeconds: 300 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - name: step to sleep + interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 1.9.99 + name: chef-platform/shell-interpreter + command: + linux: + - sleep 10 + windows: + - timeout 10 + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] diff --git a/_vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.json b/_vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.json new file mode 100644 index 0000000000..cb0ccbe1a1 --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.json @@ -0,0 +1,185 @@ +{ + "name": "Certificate rotation", + "description": "A job to demonstrate how on demand certificate rotation can be performed on servers. It uses inspec to check for expiry and shell for fixing", + "scheduleRule": "immediate", + "exceptionRules": [], + "target": { + "executionType": "sequential", + "groups": [ + { + "timeoutSeconds": 120, + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "successCriteria": [ + { + "numRuns": { + "type": "percent", + "value": 100 + }, + "status": "success" + } + ], + "nodeListType": "nodes", + "nodeIdentifiers": ["--NODE1--"] + } + ] + }, + "actions": { + "accessMode": "agent", + "steps": [ + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "6.6.0" + }, + "name": "chef-platform/inspec-interpreter" + }, + "command": { + "exec": "scan", + "args": { + "path": "https://github.com/akshayparvatikar29/cert-compliance" + } + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": { + "INSPEC_VALUE": { + "source": "stdout", + "sourceType": "output", + "extractMethod": "regEx", + "expression": "0 successful", + "required": true, + "sensitive": false + } + }, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [], + "name": "checking the certificate" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "6.6.0" + }, + "name": "chef-platform/shell-interpreter" + }, + "inputs": {}, + "expectedInputs": { + "INSPEC_VALUE": { + "type": "string", + "sensitive": false, + "required": true, + "default": "" + } + }, + "outputFieldRules": {}, + "conditions": [ + { + "inputName": "INSPEC_VALUE", + "operator": "eq", + "value": "0 successful" + } + ], + "command": { + "linux": [ + "sudo openssl genrsa -out /home/ec2-user/compliance/certificates/server-aug24.key 2048", + "sudo openssl req -new -key /home/ec2-user/compliance/certificates/server-aug24.key -out /home/ec2-user/compliance/certificates/server-aug24.csr -config /home/ec2-user/compliance/certificates/san.cnf", + "sudo openssl x509 -req -days 31 -in /home/ec2-user/compliance/certificates/server-aug24.csr -signkey /home/ec2-user/compliance/certificates/server-aug24.key -out /home/ec2-user/compliance/certificates/server-aug24.crt -extensions req_ext -extfile /home/ec2-user/compliance/certificates/san.cnf" + ] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "none", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [], + "name": "creating certificate" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": [ + "sudo printf '\nServerName 34.224.75.161\nDocumentRoot /var/www/html\nSSLEngine on\nSSLCertificateFile /home/ec2-user/compliance/certificates/server-aug24.crt\nSSLCertificateKeyFile /home/ec2-user/compliance/certificates/server-aug24.key\n'>>/etc/httpd/conf.d/Certificate_Details.conf", + "sudo yum install mod_ssl" + ] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [], + "name": "create a file and add certificate details" + }, + { + "interpreter": { + "skill": { + "minVersion": "1.0.0", + "maxVersion": "1.9.99" + }, + "name": "chef-platform/shell-interpreter" + }, + "command": { + "linux": [ + "sudo systemctl restart httpd.service", + "sudo systemctl start firewalld", + "sudo systemctl enable firewalld", + "sudo firewall-cmd --add-service=https", + "sudo firewall-cmd --add-service=http" + ] + }, + "inputs": {}, + "expectedInputs": {}, + "outputFieldRules": {}, + "retryCount": 2, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "type": "linear", + "delaySeconds": 1, + "arguments": [1, 3, 5] + } + }, + "limits": {}, + "conditions": [], + "name": "Restart httpd service and setup firewall" + } + ] + } +} diff --git a/_vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.yaml b/_vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.yaml new file mode 100644 index 0000000000..5ee4524b4c --- /dev/null +++ b/_vendor/github.com/chef/samples/courier-job-examples/ssl_cert_rotation.yaml @@ -0,0 +1,147 @@ +--- +name: Certificate rotation +description: A job to demonstrate how on demand certificate rotation can be performed + on servers. It uses inspec to check for expiry and shell for fixing +scheduleRule: immediate +exceptionRules: [] +target: + executionType: sequential + groups: + - timeoutSeconds: 120 + batchSize: + type: number + value: 1 + distributionMethod: batching + successCriteria: + - numRuns: + type: percent + value: 100 + status: success + nodeListType: nodes + nodeIdentifiers: + - "--NODE1--" +actions: + accessMode: agent + steps: + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 6.6.0 + name: chef-platform/inspec-interpreter + command: + exec: scan + args: + path: https://github.com/akshayparvatikar29/cert-compliance + inputs: {} + expectedInputs: {} + outputFieldRules: + INSPEC_VALUE: + source: stdout + sourceType: output + extractMethod: regEx + expression: 0 successful + required: true + sensitive: false + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + name: checking the certificate + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 6.6.0 + name: chef-platform/shell-interpreter + inputs: {} + expectedInputs: {} + outputFieldRules: {} + conditions: [] + command: + linux: + - sudo openssl genrsa -out /home/ec2-user/compliance/certificates/server-aug24.key + 2048 + - sudo openssl req -new -key /home/ec2-user/compliance/certificates/server-aug24.key + -out /home/ec2-user/compliance/certificates/server-aug24.csr -config /home/ec2-user/compliance/certificates/san.cnf + - sudo openssl x509 -req -days 31 -in /home/ec2-user/compliance/certificates/server-aug24.csr + -signkey /home/ec2-user/compliance/certificates/server-aug24.key -out /home/ec2-user/compliance/certificates/server-aug24.crt + -extensions req_ext -extfile /home/ec2-user/compliance/certificates/san.cnf + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: none + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + name: creating certificate + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 6.6.0 + name: chef-platform/shell-interpreter + command: + linux: + - |- + sudo printf ' + ServerName 34.224.75.161 + DocumentRoot /var/www/html + SSLEngine on + SSLCertificateFile /home/ec2-user/compliance/certificates/server-aug24.crt + SSLCertificateKeyFile /home/ec2-user/compliance/certificates/server-aug24.key + '>>/etc/httpd/conf.d/Certificate_Details.conf + - sudo yum install mod_ssl + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + name: create a file and add certificate details + - interpreter: + skill: + minVersion: 1.0.0 + maxVersion: 6.6.0 + name: chef-platform/shell-interpreter + command: + linux: + - sudo systemctl restart httpd.service + - sudo systemctl start firewalld + - sudo systemctl enable firewalld + - sudo firewall-cmd --add-service=https + - sudo firewall-cmd --add-service=http + inputs: {} + expectedInputs: {} + outputFieldRules: {} + retryCount: 2 + failureBehavior: + action: retryThenFail + retryBackoffStrategy: + type: linear + delaySeconds: 1 + arguments: + - 1 + - 3 + - 5 + limits: {} + conditions: [] + name: Restart httpd service and setup firewall diff --git a/_vendor/github.com/chef/samples/skills/chef-client-interpreter.json b/_vendor/github.com/chef/samples/skills/chef-client-interpreter.json new file mode 100644 index 0000000000..2c03ef96eb --- /dev/null +++ b/_vendor/github.com/chef/samples/skills/chef-client-interpreter.json @@ -0,0 +1,9 @@ +{ + "name": "chef-client-interpreter", + "canister": { + "origin": "chef-platform", + "name": "chef-client-interpreter", + "service": false + }, + "configurationTemplates": [] +} \ No newline at end of file diff --git a/_vendor/github.com/chef/samples/skills/courier-runner-skill.json b/_vendor/github.com/chef/samples/skills/courier-runner-skill.json new file mode 100644 index 0000000000..d96f8ccae2 --- /dev/null +++ b/_vendor/github.com/chef/samples/skills/courier-runner-skill.json @@ -0,0 +1,17 @@ +{ + "name": "courier-runner", + "canister": { + "name": "courier-runner", + "origin": "chef-platform", + "service": true + }, + "configurationTemplates": [ + { + "content": "W2xvZ10KZGlyID0gInt7LnNldHRpbmdzLmxvZ19kaXJ9fSIKZm9ybWF0ID0gInt7LnNldHRpbmdzLmxvZ19mb3JtYXR9fSIKbGV2ZWwgPSAie3suc2V0dGluZ3MubG9nX2xldmVsfX0iCm91dHB1dCA9ICJ7ey5zZXR0aW5ncy5sb2dfb3V0cHV0fX0iCgpbbm9kZV0Kbm9kZV9pZCA9ICJ7ey5hZ2VudC5ub2RlSWR9fSIKCnt7aWYgaW5kZXggLnNldHRpbmdzICJzaGVsbF9pbnRlcnByZXRlciJ9fQpbW2ludGVycHJldGVyc11dCm5hbWUgPSAie3suc2V0dGluZ3Muc2hlbGxfaW50ZXJwcmV0ZXJ9fSIKe3tlbmR9fQp7e2lmIGluZGV4IC5zZXR0aW5ncyAicmVzdGFydF9pbnRlcnByZXRlciJ9fQpbW2ludGVycHJldGVyc11dCm5hbWUgPSAie3suc2V0dGluZ3MucmVzdGFydF9pbnRlcnByZXRlcn19Igp7e2VuZH19Cnt7aWYgaW5kZXggLnNldHRpbmdzICJpbnNwZWNfaW50ZXJwcmV0ZXIifX0KW1tpbnRlcnByZXRlcnNdXQpuYW1lID0gInt7LnNldHRpbmdzLmluc3BlY19pbnRlcnByZXRlcn19Igp7e2VuZH19Cnt7aWYgaW5kZXggLnNldHRpbmdzICJjaGVmX2NsaWVudF9pbnRlcnByZXRlciJ9fQpbW2ludGVycHJldGVyc11dCm5hbWUgPSAie3suc2V0dGluZ3MuY2hlZl9jbGllbnRfaW50ZXJwcmV0ZXJ9fSIKe3tlbmR9fQoKW3JlcG9ydGVyXQpuYW1lID0gInt7LnNldHRpbmdzLnJlcG9ydGVyX25hbWV9fSIKYXV0aGVudGljYXRpb25UeXBlID0gICJ7ey5zZXR0aW5ncy5yZXBvcnRlcl9hdXRoZW50aWNhdGlvbl90eXBlfX0iCmRpciA9ICJ7ey5zZXR0aW5ncy5yZXBvcnRlcl9kaXJ9fSIKaW50ZXJuYWxJblNlYyA9IHt7LnNldHRpbmdzLnJlcG9ydGVyX2ludGVydmFsX2luX3NlY319CnJldHJ5SW50ZXJ2YWxJblNlYyA9IHt7LnNldHRpbmdzLnJlcG9ydGVyX3JldHJ5X2ludGVydmFsX2luX3NlY319CnRvdGFsUmV0cnlEdXJhdGlvbkluTWluID0ge3suc2V0dGluZ3MucmVwb3J0ZXJfdG90YWxfcmV0cnlfZHVyYXRpb25faW5fbWlufX0KCltnYXRld2F5X2NvbmZpZ10KdGVuYW50ZnFkbnMgPSAie3suYWdlbnQudGVuYW50RnFkbnN9fSIKbm9kZV9yb2xlX2xpbmtfaWQgPSAie3suc2tpbGwubm9kZVJvbGVMaW5rSWR9fSIKcGxhdGZvcm1fY3JlZGVudGlhbF9wYXRoID0gInt7LnNraWxsLnBsYXRmb3JtQ3JlZGVudGlhbHNQYXRofX0iCnJvb3RfY2FfcGF0aCA9ICJ7ey5hZ2VudC5yb290Q2FQYXRofX0iCmluc2VjdXJlID0gInt7LmFnZW50Lmluc2VjdXJlfX0iCgpbcXVldWVdCnByb3ZpZGVyID0gMA==", + "fileName": "user.toml", + "filePath": "/hab/user/courier-runner/config", + "name": "courier-runner-template", + "windowsFilePath": "c:\\hab\\user\\courier-runner\\config" + } + ] +} diff --git a/_vendor/github.com/chef/samples/skills/gohai-skill.json b/_vendor/github.com/chef/samples/skills/gohai-skill.json new file mode 100644 index 0000000000..4f08e0ec34 --- /dev/null +++ b/_vendor/github.com/chef/samples/skills/gohai-skill.json @@ -0,0 +1,17 @@ +{ + "name": "chef-gohai", + "canister": { + "origin": "chef-platform", + "name": "chef-gohai", + "service": true + }, + "configurationTemplates": [ + { + "content": "W2dvaGFpXQpub2RlX2lkID0gInt7LmFnZW50Lm5vZGVJZH19Igpub2RlX3JvbGVfbGlua19pZCA9ICJ7ey5za2lsbC5ub2RlUm9sZUxpbmtJZH19IgpwbGF0Zm9ybV9jcmVkZW50aWFsc19wYXRoID0gInt7LnNraWxsLnBsYXRmb3JtQ3JlZGVudGlhbHNQYXRofX0iCmluc2VjdXJlID0ge3suYWdlbnQuaW5zZWN1cmV9fQpyb290X2NhX3BhdGggPSAie3suYWdlbnQucm9vdENhUGF0aH19IgoKW2FwaV0KdGVuYW50X2ZxZG5zID0gInt7LmFnZW50LnRlbmFudEZxZG5zfX0iCgpbbG9nZ2VyXQpsb2dfbGV2ZWwgPSAie3suc2V0dGluZ3MubG9nX2xldmVsfX0iCmxvZ190b19zdGRvdXQgPSB7ey5zZXR0aW5ncy5sb2dfdG9fc3Rkb3V0fX0KbG9nX3RvX2ZpbGUgPSB7ey5zZXR0aW5ncy5sb2dfdG9fZmlsZX19CmxvZ19maWxlX3BhdGggPSAie3suc2V0dGluZ3MubG9nX2ZpbGVfcGF0aH19Ig==", + "fileName": "user.toml", + "filePath": "/hab/user/chef-gohai/config", + "name": "default", + "windowsFilePath": "c:\\hab\\user\\chef-gohai\\config" + } + ] +} \ No newline at end of file diff --git a/_vendor/github.com/chef/samples/skills/inspec-interpreter-skill.json b/_vendor/github.com/chef/samples/skills/inspec-interpreter-skill.json new file mode 100644 index 0000000000..e4ceac47fd --- /dev/null +++ b/_vendor/github.com/chef/samples/skills/inspec-interpreter-skill.json @@ -0,0 +1,9 @@ +{ + "name": "inspec-interpreter", + "canister": { + "origin": "chef-platform", + "name": "inspec-interpreter", + "service": false + }, + "configurationTemplates": [] +} \ No newline at end of file diff --git a/_vendor/github.com/chef/samples/skills/restart-interpreter-skill.json b/_vendor/github.com/chef/samples/skills/restart-interpreter-skill.json new file mode 100644 index 0000000000..ac4355f32d --- /dev/null +++ b/_vendor/github.com/chef/samples/skills/restart-interpreter-skill.json @@ -0,0 +1,9 @@ +{ + "name": "restart-interpreter", + "canister": { + "origin": "chef-platform", + "name": "restart-interpreter", + "service": false + }, + "configurationTemplates": [] +} \ No newline at end of file diff --git a/_vendor/github.com/chef/samples/skills/shell-interpreter-skill.json b/_vendor/github.com/chef/samples/skills/shell-interpreter-skill.json new file mode 100644 index 0000000000..56a64d56db --- /dev/null +++ b/_vendor/github.com/chef/samples/skills/shell-interpreter-skill.json @@ -0,0 +1,9 @@ +{ + "name": "shell-interpreter", + "canister": { + "origin": "chef-platform", + "name": "shell-interpreter", + "service": false + }, + "configurationTemplates": [] +} \ No newline at end of file diff --git a/_vendor/modules.txt b/_vendor/modules.txt index 698f2b7062..b91974a145 100644 --- a/_vendor/modules.txt +++ b/_vendor/modules.txt @@ -14,6 +14,7 @@ # github.com/chef/compliance-profiles/docs-chef-io v0.0.0-20250207053335-f11d6ce5b3c1 # github.com/chef/compliance-remediation-2022/docs-chef-io v0.0.0-20240313054833-ebbc45209efa # github.com/chef/license-service/docs-chef-io v0.0.0-20250120051510-ae1de80f4621 +# github.com/chef/samples v0.0.0-20250304162216-b7bf3710b07e # github.com/chef/chef-docs-theme v0.0.0-20250217213320-727f9bce8258 # github.com/FortAwesome/Font-Awesome v0.0.0-20240108205627-a1232e345536 # github.com/cowboy/jquery-hashchange v0.0.0-20100902193700-0310f3847f90 diff --git a/config/_default/menu.toml b/config/_default/menu.toml index b793b0c3eb..21a48e7295 100644 --- a/config/_default/menu.toml +++ b/config/_default/menu.toml @@ -677,15 +677,30 @@ identifier = "chef_infra" #### #### -# Chef SaaS Menu +# Chef Cloud Menu #### -[[saas]] -title = "Chef SaaS" -identifier = "chef_saas" +[[cloud]] +title = "Chef Cloud" +identifier = "chef_cloud" + + [[cloud]] + title = "Chef 360 SaaS" + identifier = "chef_cloud/360" + parent = "chef_cloud" + + [[cloud]] + title = "Get started" + identifier = "chef_cloud/360/get_started" + parent = "chef_cloud/360" + + [[cloud]] + title = "Chef Saas" + identifier = "chef_cloud/saas" + parent = "chef_cloud" #### -# End Chef SaaS Menu +# End Chef Cloud Menu #### #### diff --git a/config/_default/module.toml b/config/_default/module.toml index de91fca655..e20dc9799c 100644 --- a/config/_default/module.toml +++ b/config/_default/module.toml @@ -364,6 +364,19 @@ workspace = '' source = "assets" target = "assets" +### +# Mount chef/samples +### + +[[imports]] + disable = false + ignoreConfig = false + path = "github.com/chef/samples" + +[[imports.mounts]] + source = '.' + target = 'static/samples' + ### # Mount Hugo theme ### diff --git a/config/_default/params.toml b/config/_default/params.toml index 1e6e473921..d0f6110ba7 100644 --- a/config/_default/params.toml +++ b/config/_default/params.toml @@ -4,12 +4,12 @@ menuOrder = [ "overview", "360", "automate", + "cloud", "desktop", "habitat", "infra", "server", "inspec", - "saas", "workstation", "effortless", "supermarket", diff --git a/content/360/saas/_index.md b/content/360/saas/_index.md new file mode 100644 index 0000000000..70e47c7ebc --- /dev/null +++ b/content/360/saas/_index.md @@ -0,0 +1,38 @@ ++++ +title = "Progress Chef 360 SaaS" +linkTitle = "Chef 360 SaaS" + +[cascade] + [cascade.params] + product = ['chef-360-saas'] + +[menu.cloud] +title = "Overview" +parent = "chef_cloud/360" +identifier = "chef_cloud/360/overview" +weight = 10 ++++ + +Chef 360 SaaS focuses on job orchestration and node management in the cloud to complete your DevOPS journeys whenever, wherever, and however a business scenario requires. Chef 360 SaaS is hosted, maintained, and upgraded by Chef allowing you to focus on your workflows. + +**Whenever**: The Chef 360 SaaS Platform provides real-time observability of the changing infrastructure environment through scheduled actions, continuous scanning or immediate “execute-once" semantics. + +**Wherever**: The Chef 360 SaaS Platform operates across hybrid environments from on-premises data centers through to all major public clouds, and secures the wide variety of platforms and resources supported by Chef. + +**Whatever**: The Chef 360 SaaS Platform enables DevOps and security engineering teams—whether they follow ITIL or ChatOps—to leverage the native JSON syntax or use one of several, extensible infrastructure-as-code DSLs. + +The Chef 360 SaaS Platform has a workflow engine to execute varied jobs in compliance and infrastructure management: + +- Regularly scan, audit, and remediate infrastructure, protecting your fleet with certified industry compliance profiles like CIS, SOC2, and CSPM. +- Create composable jobs quickly using shell scripting and out-of-the-box skills to develop full playbooks, capable of coordinating the other DevOps IaC tools you own. +- Safely build, package, and deploy applications from a fully cloud-native, zero-trust platform in conjunction with Chef Habitat. +- Discover assets effortlessly from existing Chef environments, other Progress products like What’s-Up-Gold, and even your own CMDB and monitoring solutions. +- Leverage an open partner ecosystem with Chef premium content and content from thought leaders such as OSL and MITRE, and easily extensible formats which require no special knowledge. + +## Additional guides + +- [Chef 360 user interface](https://docs.chef.io/360/1.2/chef_360_ui/) +- [Chef Courier](https://docs.chef.io/360/1.2/courier/) +- [Chef Node Management](https://docs.chef.io/360/1.2/courier/jobs/) +- [Organization and user management](https://docs.chef.io/360/1.2/administration/) +- [API and CLI references](https://docs.chef.io/360/1.2/reference/) diff --git a/content/360/saas/get_started/_index.md b/content/360/saas/get_started/_index.md new file mode 100644 index 0000000000..9902d2dc12 --- /dev/null +++ b/content/360/saas/get_started/_index.md @@ -0,0 +1,37 @@ ++++ +title = "Get started with Chef 360 Platform on-prem" +linkTitle = "Get started" + +[menu.cloud] +title = "Overview" +identifier = "chef_cloud/360/get_started/overview" +parent = "chef_cloud/360/get_started" +weight = 10 ++++ + +This section provides quickstart guides for getting started with Chef 360 Platform and its tools. + +## Get started guides + +Before you begin with these guides, [review the system requirements]({{< relref "system_requirements" >}}). + +Chef 360 SaaS guides: + +- [Set up Chef 360 SaaS]({{< relref "set_up" >}}) + +Chef 360 Platform CLI guides: + +- [Install and register the Chef 360 Platform CLIs]({{< relref "install_cli" >}}) + +Chef Node Management guides: + +- [Register the Node Management agent]({{< relref "register_node_agent" >}}) +- [Define skills]({{< relref "define_skills" >}}) +- [Create a skill assembly]({{< relref "create_skill_assembly" >}}) +- [Create override settings]({{< relref "override_settings" >}}) +- [Create a node cohort]({{< relref "node_cohort" >}}) +- [Enroll nodes]({{< relref "enroll_nodes" >}}) + +Chef Courier job guides: + +- [Run jobs with Chef Courier]({{< relref "jobs" >}}) diff --git a/content/360/saas/get_started/create_skill_assembly.md b/content/360/saas/get_started/create_skill_assembly.md new file mode 100644 index 0000000000..9b742909a6 --- /dev/null +++ b/content/360/saas/get_started/create_skill_assembly.md @@ -0,0 +1,33 @@ ++++ +title = "Create a skill assembly" + +[menu.cloud] +title = "Create a skill assembly" +identifier = "chef_cloud/360/get_started/skill assembly" +parent = "chef_cloud/360/get_started" +weight = 70 ++++ + +A skill assembly defines a set of skills should be installed or removed from nodes using add and remove rules. + +## Prerequisites + +- [Skills are defined]({{< relref "define_skills" >}}). + +## Create a skill assembly + +To create a skill assembly, follow these steps: + +{{< readfile file="content/360/saas/reusable_text/md/skill_assembly_get_started.md" >}} + +## Troubleshooting + +Use the `assembly find-one-assembly` subcommand to verify that the skill assembly was created or updated successfully: + +```sh +chef-node-management-cli management assembly find-one-assembly --skillAssemblyId --profile +``` + +## Next steps + +- [Create override settings]({{< relref "override_settings.md" >}}) that define required skill settings. diff --git a/content/360/saas/get_started/define_skills.md b/content/360/saas/get_started/define_skills.md new file mode 100644 index 0000000000..f070c0bb38 --- /dev/null +++ b/content/360/saas/get_started/define_skills.md @@ -0,0 +1,131 @@ ++++ +title = "Define skills" + +[menu.cloud] +title = "Define skills" +identifier = "chef_cloud/360/get_started/skills" +parent = "chef_cloud/360/get_started" +weight = 60 ++++ + +This document describes how to define the set of required skills on a node or set of nodes. + +A skill is an agent that gives you the ability to perform actions on a node to achieve an outcome. + +## Prerequisites + +- [Node Management agent is registered]({{< relref "register_node_agent" >}}). +- The Chef Infra Client interpreter requires Chef Infra Client installed on each node. +- The Chef InSpec interpreter requires Chef InSpec installed on each node. + +## Create skill definitions + +The following Chef 360 Platform skills are required or recommended for managing nodes, running actions, and returning action results: + +- Courier Runner skill +- Gohai skill +- Shell interpreter skill +- Restart interpreter skill +- Chef Client interpreter skill + +### Courier Runner + +The Courier Runner skill interprets the Courier Job definitions sent to it by the Courier Dispatcher and executes them on the node. + +1. Create a JSON file called `courier-runner-skill.json` containing the following skill definition for Courier Runner: + + {{% readfile file="_vendor/github.com/chef/samples/skills/courier-runner-skill.json" highlight="json" %}} + + {{< note >}} If the skill is registered as a service, then the `name` and `canister.name` fields must be identical. {{< /note >}} + +1. Create the skill: + + ```sh + chef-node-management-cli management skill create-skill --body-file courier-runner-skill.json --profile + ``` + +### Gohai + +The Gohai skill collects attributes about a node in addition to attributes collected by the Node Management agent. + +1. Create a file named `gohai-skill.json` containing the skill definition for gohai. + + {{% readfile file="_vendor/github.com/chef/samples/skills/gohai-skill.json" highlight="json" %}} + + {{< note >}} If the skill is registered as a service, then the `name` and `canister.name` fields must be identical. {{< /note >}} + +1. Create the skill: + + ```sh + chef-node-management-cli management skill create-skill --body-file gohai-skill.json --profile + ``` + +### Shell interpreter + +The Shell interpreter skill executes OS commands in a Courier Job. + +1. Create a file named `shell-interpreter-skill.json` containing the skill definition: + + {{% readfile file="_vendor/github.com/chef/samples/skills/shell-interpreter-skill.json" highlight="json" %}} + +1. Create the skill: + + ```sh + chef-node-management-cli management skill create-skill --body-file shell-interpreter-skill.json --profile + ``` + +### Restart interpreter + +If your jobs will reboot a node, then you need the Restart interpreter skill. + +1. Create a file named `restart-interpreter-skill.json` containing the skill definition. + + {{% readfile file="_vendor/github.com/chef/samples/skills/restart-interpreter-skill.json" highlight="json" %}} + +1. Create the skill: + + ```sh + chef-node-management-cli management skill create-skill --body-file restart-interpreter-skill.json --profile + ``` + +### Chef Infra Client interpreter + +If your Courier jobs will invoke Infra Client runs, then you need the Chef Infra Client interpreter skill. + +1. Create a file named `chef-client-interpreter-skill.json` and add the following the skill definition. + + {{% readfile file="_vendor/github.com/chef/samples/skills/chef-client-interpreter.json" highlight="json" %}} + +1. Create the skill: + + ```sh + chef-node-management-cli management skill create-skill --body-file chef-client-interpreter-skill.json --profile + ``` + +### Chef InSpec interpreter + +If your Courier jobs will invoke Chef InSpec scans, then you need the Chef InSpec interpreter skill. + +1. Create a file named `inspec-interpreter-skill.json` and add the following skill definition. + + {{% readfile file="_vendor/github.com/chef/samples/skills/inspec-interpreter-skill.json" highlight="json" %}} + +1. Create the skill: + + ```sh + chef-node-management-cli management skill create-skill --body-file inspec-interpreter-skill.json --profile + ``` + +## Verify skills + +- Get a list of all the defined skills using the `find-all-skills` subcommand: + + ```sh + chef-node-management-cli management skill find-all-skills --profile + ``` + + It returns an output listing the defined skills. + +## Next step + +- [Create a skill assembly]({{< relref "create_skill_assembly.md" >}}) that adds or removes skills from nodes. diff --git a/content/360/saas/get_started/enroll_nodes.md b/content/360/saas/get_started/enroll_nodes.md new file mode 100644 index 0000000000..b7349b98ed --- /dev/null +++ b/content/360/saas/get_started/enroll_nodes.md @@ -0,0 +1,216 @@ ++++ +title = "Enroll nodes" + +[menu.cloud] +title = "Enroll nodes" +identifier = "chef_cloud/360/get_started/enroll_nodes" +parent = "chef_cloud/360/get_started" +weight = 100 ++++ + +Node enrollment brings nodes under management by Chef 360 Platform. + +This document demonstrates two different methods of node enrollment: + +- cookbook-based enrollment +- single-node enrollment + +{{< note >}} + +This version of Chef 360 Platform doesn't support node re-enrollment. + +{{< /note >}} + +## Prerequisites + +- [A node cohort has been created]({{< relref "node_cohort" >}}). + +## Requirements + +Review the [node requirements]({{< relref "system_requirements#node-requirements" >}}) before enrolling nodes. + +## Single-node enrollment + +Single-node enrollment enrolls nodes from the server side. +With this method, you define connection and configuration details and push them up to Chef 360 Platform, which connects to each node and installs Chef Habitat, Chef Node Management, and any skills or agents assigned to a node cohort. + +### Enroll Linux nodes + +To enroll a Linux node, follow these steps: + +1. Create a JSON file that defines the node connection settings: + + {{% readfile file="content/360/saas/reusable_text/json/enroll-node-linux-rsa.json" highlight="json" %}} + + {{< note >}} + + Format SSH keys in a JSON payload as a single-line string. + To add a multiline key, replace new lines with the newline character `\n`. + + Use the following command to replace new lines in a PEM file: + + ```sh + awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' + ``` + + {{< /note >}} + + Replace the following: + + - `` with the ID of the cohort that the node will be enrolled with. + - `` with a public domain name or IP address. + - `` with the SSH username to authenticate with the node. + - `` with the SSH key used to authenticate with the node. + - `` with the SSH port. Default is `22`. + + {{< note >}} + + You can also authenticate with an SSH password instead of an RSA key. To do so, replace `key` with `password` in the SSH connection settings file. For example, `"password": ""`. + + {{< /note >}} + +1. Enroll the node using the `enrollment enroll-node` command: + + ```sh + chef-node-management-cli enrollment enroll-node --body-file --profile + ``` + + The response is similar to the following: + + ```json + { + "item": { + "id": "36c570b1-798a-4530-ada5-2661dfeb3fac", + "nodeId": "e4b1b524-4e77-4448-b1a9-01b80288c898" + } + } + ``` + +### Enroll Windows nodes + +To enroll a Windows node, follow these steps: + +1. Create a JSON file that defines the node connection settings: + + {{% readfile file="content/360/saas/reusable_text/json/enroll-node-windows.json" highlight="json" %}} + + Replace the following: + + - `` with the ID of the cohort that the node will be enrolled with. + - `` with the node's public domain name or IP address. + - `` with the Windows username to authenticate with the node. + - `` with the Windows password used to authenticate with the node. + +1. Enroll the node using the `enrollment enroll-node` command: + + ```sh + chef-node-management-cli enrollment enroll-node --body-file --profile + ``` + + The response is similar to the following: + + ```json + { + "item": { + "id": "36c570b1-798a-4530-ada5-2661dfeb3fac", + "nodeId": "e4b1b524-4e77-4448-b1a9-01b80288c898" + } + } + ``` + +## Cookbook-based enrollment + +With cookbook-based enrollment, you enroll nodes from the client side by uploading a [cookbook](https://docs.chef.io/cookbooks/) with enrollment settings to Chef Infra Server and then Chef Infra Client enrolls the node with Chef 360 Platform. + +### Enroll nodes + +The `chef-cookbook-enroll` cookbook uses the `node_management_enroll` custom resource and a [wrapper cookbook](https://www.chef.io/blog/writing-wrapper-cookbooks) to define enrollment settings. + +To configure the cookbooks and define enrollment settings, follow these steps: + +1. Download the [`chef360-node-enroll` cookbook](https://supermarket.chef.io/cookbooks/chef360-node-enroll). + +1. Upload the `chef360-node-enroll` cookbook, which includes the `node_management_enroll` resource, to your Chef Infra Server: + + ```bash + knife cookbook upload chef360-node-enroll --cookbook-path + ``` + + Replace `COOKBOOK_DIR_PATH` with the path to your cookbook directory. + +1. Create a wrapper cookbook and add the `chef360-node-enroll` cookbook as a dependency: + + ```sh + chef generate cookbook + ``` + + In the [`metadata.rb` file](https://docs.chef.io/config_rb_metadata/) of your wrapper cookbook, add the following dependency to include the `chef-cookbook-enroll` cookbook: + + ```ruby + depends 'chef360-node-enroll', '~> 1.0.0' + ``` + +1. Define the `node_management_enroll` resource in your wrapper cookbook's recipe: + + ```ruby + node_management_enroll 'Enroll Node' do + chef_platform_url '' + enroll_type '' + api_port '' + access_key '' + secret_key '' + cohort_id '' + hab_builder_url '' + working_dir_path '' + upgrade_skills + end + ``` + + Replace: + + - `` with the fully qualified domain name (FQDN) for your Chef 360 Platform deployment. + - `` with either `full` or `partial` depending on the form of enrollment. Use `full` unless you must `partial`. + - `` with the API port configured in Chef 360 Platform. The default value is `31000`. + - `` with an access key for secure communication with Chef 360 Platform. Store securely using an [encrypted Chef data bag](https://docs.chef.io/data_bags/) or a [secrets manager](https://docs.chef.io/infra_language/secrets/). + - `` with a secret key for secure communication with Chef 360 Platform. Store securely using an [encrypted Chef data bag](https://docs.chef.io/data_bags/) or a [secrets manager](https://docs.chef.io/infra_language/secrets/). + - `` with a valid cohort UUID. The cohort defines all skills and settings installed on the node. + - `` with the URL of the Chef Habitat Builder used by your organization. Default value: `https://bldr.habitat.sh` + - `` with a temporary working directory where all required builds are downloaded. Specify a valid path based on the OS. Default value: `/tmp`. + - `` with `true` or `false`. If `true`, Chef 360 Platform checks for the latest skill versions and installs them if found. Default value: `false`. + +1. Push the wrapper cookbook or policy to the Chef Infra Server. + + 1. If you're using a role, [upload](https://docs.chef.io/workstation/knife_cookbook/#upload) the wrapper cookbook to the Chef Infra Server: + + ```bash + knife cookbook upload --cookbook-path + ``` + + 1. If you're using a Policyfile, [create `Policyfile.lock.json` file](https://docs.chef.io/workstation/ctl_chef/#chef-install) and [push](https://docs.chef.io/workstation/ctl_chef/#chef-push) the Policyfile to Chef Infra Server: + + ```bash + chef install + chef push + ``` + +1. Include the wrapper cookbook in your node's run-list by adding it to a role or Policyfile. See the [run-list](https://docs.chef.io/run_lists/) and [role](https://docs.chef.io/roles/#manage-roles) documentation for more information. + + The next time Chef Infra Client runs, it executes the `node_management_enroll` resource and the node is enrolled with Chef 360 Platform. + +## Check the node enrollment status + +{{< readfile file="content/360/saas/reusable_text/md/node_enrollment_status_node_id.md" >}} + +## Verify that the skills are installed + +- Verify that the skills are installed: + + ```sh + chef-node-management-cli management node find-one-node --nodeId --profile + ``` + + The response includes a list of the installed skills. + +## Next step + +- [Create a Courier job]({{< relref "jobs.md" >}}). diff --git a/content/360/saas/get_started/install_cli.md b/content/360/saas/get_started/install_cli.md new file mode 100644 index 0000000000..abb3756959 --- /dev/null +++ b/content/360/saas/get_started/install_cli.md @@ -0,0 +1,164 @@ ++++ +title = "Install CLIs and register your workstation" + +draft = false + +[menu.cloud] +title = "Install CLIs" +identifier = "chef_cloud/360/get_started/cli" +parent = "chef_cloud/360/get_started" +weight = 40 ++++ + +This page documents how to download and install the Chef 360 Platform CLIs and register your workstation with your Chef 360 Platform deployment. + +## Prerequisites + +- [Chef 360 SaaS configured]({{< relref "set_up" >}}). +- `/usr/local/bin` is present in the PATH environment variable. + +## Install CLIs + +{{< readfile file="content/360/saas/reusable_text/md/clis_install_saas.md" >}} + +## Install and configure the bash-completion package + +{{< readfile file="content/360/saas/reusable_text/md/install_bash_completion.md" >}} + +## Add your license + +{{< readfile file="content/360/saas/reusable_text/md/clis_add_license.md" >}} + +## Verify profiles + +{{< readfile file="content/360/saas/reusable_text/md/clis_verify_profiles.md" >}} + +## Assign the Node Manager and Courier Operator roles + +The `node-manager` and `courier-operator` roles allow you to manage nodes, manage skills on nodes, and run Chef Courier jobs. + +Before you begin, ensure you have: + +- Your user ID. Use the `user-account identity get-self-user` subcommand to get your user ID. +- The name of a profile with the org-admin role. + +Follow this step to give your user account the `node-manager` and `courier-operator` roles: + +- Assign the `node-manager` role and `courier-operator` role using the `user-account user assign-role` subcommand: + + ```sh + chef-platform-auth-cli user-account user assign-role --body '{"name": "node-manager", "roleId": "6e7df273-928b-41ec-b6f6-e3f5138a6f9e"}' --userId --profile + ``` + + ```sh + chef-platform-auth-cli user-account user assign-role --body '{"name": "courier-operator", "roleId": "ac12c3a6-95f7-429d-b3fc-584ce1cf74de"}' --userId --profile + ``` + + Replace: + + - `` with your user ID. + - `` with your profile that has the org-admin role. + +## Create profiles for the Node Manager and Courier Operator roles + +Create a profile _for each role_ that you added to your user account in the previous step. + +To create a profile, follow these steps: + +1. Create a profile using the `register-device` subcommand that associates your workstation with a specific tenant, organization, and role: + + ```sh + chef-platform-auth-cli register-device --device-name --profile-name --url + ``` + + {{< note >}} + + If you've configured Chef 360 Platform with a system-generated or custom certificate in the API/UI settings, use the following CLI arguments: + + - If you don't have the root certificate authority, use the `--insecure` flag. This flag skips certificate validation. + - If have the root certificate authority present, use the `--cafile ` flag. + + {{< /note >}} + + Replace: + + - `` with a name for the workstation. + - `` with a profile name for the role that this profile will use. For example, add the `courier-operator` profile name for the `courier-operator` role. + - `` with the tenant URL, for example `https://chef360.example.com:31000`. + + The CLI responds with an authorization code that includes a link to log into Chef 360 Platform. + + ```sh + Device Id : ac:de:48:00:11:22-admin-chef-courier-cli + Device Name : + OAuth Code : + + Please log in and authorise the the device by using the link below: + https://chef360.example.com/platform/user-accounts/v1/identity/device/ac:de:48:00:11:22-admin-chef-courier-cli/authorise?oauthCode=&appType=chef-courier-cli&deviceName= + + Is the device authorised? (y or n) + ``` + + Paste the link into your browser and log in. + The CLI waits for the device registration process to finish in the browser. + +1. Open a browser, navigate to the link returned by the CLI, and log in if you haven't already. + +1. Select the organization and role you would like to link to this profile and select **Submit**. + + {{< figure src="/images/360/select-role.png" width="500px" alt="Chef 360 Platform organization and role selection screen." >}} + +1. On the **Device Authorization** screen, Chef 360 Platform shows your OAuth code and you can select an expiration date for your session. + + Chef 360 Platform automatically refreshes your access token up to this expiration date. + + After entering this information, select **Authorize**. + + {{< figure src="/images/360/setting-expiry-token.png" alt="Chef 360 Platform device authorization screen with OAuth token and expiration date." width="500px">}} + +1. Return to your terminal and enter `y` to continue. + + The CLI displays your device profile and your workstation is authorized to access Chef 360 Platform services. + + ```sh + Is the device authorised? (y or n) + > y + Profile: + + [tenant-org-role] + DeviceId = "ac:de:48:00:11:22-admin-chef-courier-cli" + Url = "https://demo.chef360.io/" + OrgName = "Demo Organization" + RoleName = "org-admin" + AccessKey = "FIT3SXM...TCYK4V05Y" + SecretKey = "Cwaygh4FqE2sT...rX4wBu0hp9IE9YpzoGuX" + + Device registered successfully + ``` + +1. Optional: Test your connection by getting the role associated with your user account: + + ```sh + chef-platform-auth-cli user-account self get-role --profile + ``` + + Replace `` with the name of your profile. + +1. Optional: Set your new profile as the default profile. + + The Chef 360 Platform CLIs use a default profile automatically in any command that accepts the `--profile` argument. + If you don't set a default profile, you will have to specify it in each command with `--profile `. + + Set a default profile: + + ```sh + chef-platform-auth-cli set-default-profile + ``` + + Replace `` with the name of the default profile. + +1. Repeat this procedure so that you have separate profiles for the Node Manager and Courier Operator roles. + +## Next step + +- [Register the Node Management agent]({{< relref "register_node_agent.md" >}}). diff --git a/content/360/saas/get_started/jobs.md b/content/360/saas/get_started/jobs.md new file mode 100644 index 0000000000..79df6a43f8 --- /dev/null +++ b/content/360/saas/get_started/jobs.md @@ -0,0 +1,291 @@ ++++ +title = "Run a Courier job on a node" + +[menu.cloud] +title = "Run Courier jobs" +identifier = "chef_cloud/360/get_started/jobs" +parent = "chef_cloud/360/get_started" +weight = 110 ++++ + +A Courier job defines the actions performed on a node or set of nodes, the schedule that the actions are performed on, and the group of nodes that the actions are performed on. +A job can be executed multiple times across multiple nodes for multiple actions. + +## Prerequisites + +- [Nodes are enrolled]({{< relref "enroll_nodes" >}}). + +## Define a job + +Jobs are defined using a job template, which is a file in JSON, YAML, or TOML format that tells Chef Courier the name of the job, when the job should run, the nodes that the job should run on, and the actions that the job should take. + +This job template creates a job that's executed one node, it runs immediately, and it uses the `chef-platform/shell-interpreter` to run the `sleep 10` command. + +- Create a file called `create-job-simple.json` and with the following JSON string: + + {{% readfile file="_vendor/github.com/chef/samples/courier-job-examples/create-job-simple.json" highlight="json" %}} + + Replace `` in the JSON file with the node identifier of your enrolled node. + +## Create the job + +When you add the job to Chef 360 Platform, the Courier Dispatcher sends the job definition to the Courier Runner on the specified node which determines when and how to run the job. +You can submit a job definition using a JSON, YAML, or TOML file. The default format is JSON. + +- Add the job run using the job template file: + + ```sh + chef-courier-cli scheduler jobs add-job --body-file create-job-simple.json --profile + ``` + + The default file format is JSON, you can also submit the job using YAML or TOML using the `--body-format` option. For example: + + ```sh + chef-courier-cli scheduler jobs add-job --body-file create-job-simple.yaml --body-format yaml + ``` + + The response is similar to the following: + + ```json + { + "item": { + "exceptionReasons": [], + "id": "61013744-bd6e-437c-a995-b6211318624e", + "nextExecutionTime": "2024-03-27T14:57:20.551342549Z" + } + } + ``` + + The output includes the job ID (`61013744-bd6e-437c-a995-b6211318624e` in the example response), which can be used to for tracking the job. + +## Get the job instance details + +A job instance is created every time the job executes. This job is set to run immediately, so only one job instance is created. + +- Get the details of the job instance using the job ID: + + ```sh + chef-courier-cli state instance list-all --job-id --profile + ``` + + The response is similar to the following: + + ```json + + { + "items": [ + { + "actionSpec": { + "accessMode": "agent", + "steps": [ + { + "command": { + "linux": [ + "sleep 10" + ] + }, + "conditions": [], + "description": "", + "expectedInputs": {}, + "failureBehavior": { + "action": "retryThenFail", + "retryBackoffStrategy": { + "arguments": [ + 1, + 3, + 5 + ], + "delaySeconds": 0, + "type": "none" + } + }, + "inputs": {}, + "interpreter": { + "name": "chef-platform/shell-interpreter", + "skill": { + "maxVersion": "", + "minVersion": "1.0.0" + } + }, + "limits": { + "cores": 0, + "cpu": 1, + "timeoutSeconds": 0 + }, + "name": "sleep", + "outputFieldRules": {}, + "retryCount": 2 + } + ] + }, + "createdAt": "2024-07-12T01:10:20.064474Z", + "id": "befe88f3-ac3f-4bad-9e1a-6017332929ab", + "jobId": "448ecaf3-5e44-4e7b-9e98-62dfa8c69b1c", + "lastUpdatedBy": "00000000-0000-0000-0000-000000000000", + "status": "running", + "targetSpec": { + "executionType": "sequential", + "groups": [ + { + "batchSize": { + "type": "number", + "value": 1 + }, + "distributionMethod": "batching", + "filter": null, + "filterId": "00000000-0000-0000-0000-000000000000", + "listId": "00000000-0000-0000-0000-000000000000", + "nodeIdentifiers": [ + "1f4c680d-4dc6-4edf-83b6-ded81388f244", + "020ab866-9d3d-4ca7-919d-c21b4f9ef2a4", + "925f244c-65b4-4ab9-9ebd-4b17f8e2277b" + ], + "nodeListType": "nodes", + "successCriteria": [ + { + "numRuns": { + "type": "percent", + "value": 100 + }, + "status": "success" + } + ], + "timeoutSeconds": 60 + } + ] + }, + "updatedAt": "2024-07-12T01:10:20.064474Z" + } + ], + "pagination": { + "itemsPerPage": 10, + "nextLink": "", + "page": 1, + "pageItemCount": 1, + "previousLink": "", + "startIndex": 1, + "totalItems": 1, + "totalPages": 1 + } + } + ``` + + The response includes the job instance ID (`"id": "befe88f3-ac3f-4bad-9e1a-6017332929ab"`), which you can use to track the job instance. + +## Get job run details + +A job run is created for each target node in a job instance. + + + +- Request the details of each job run using the instance ID: + + ```sh + chef-courier-cli state instance list-instance-runs --instanceId --profile + ``` + + The response is similar to the following: + + ```json + { + "items": [ + { + "groupNumber": 0, + "lastUpdateTime": "2024-03-27T15:00:09.185273Z", + "nodeId": "03ba18c0-68b2-43ba-93fd-b6952443421e", + "receivedTime": "2024-03-27T14:58:57.226555Z", + "runId": "496f0d9a-f0be-4cb7-8cbb-2285b5c42045", + "status": "success" + }, + { + "groupNumber": 0, + "lastUpdateTime": "2024-03-27T14:58:48.582415Z", + "nodeId": "2768a3b5-f5a6-45ae-a8b6-42d531c6416a", + "receivedTime": "2024-03-27T14:57:51.753876Z", + "runId": "306d3a00-d483-4aa2-bb09-1cd8c91c15e8", + "status": "success" + }, + { + "groupNumber": 1, + "lastUpdateTime": "2024-03-27T14:58:51.090507Z", + "nodeId": "a8b1f470-fedc-45e8-ba0a-b26dd551c1d0", + "receivedTime": "2024-03-27T14:57:49.229442Z", + "runId": "376226b9-f916-42a1-8620-a4636598c5e5", + "status": "success" + }, + { + "groupNumber": 1, + "lastUpdateTime": "2024-03-27T14:59:58.186538Z", + "nodeId": "acb38595-64af-4532-8589-2aeb2ad876fc", + "receivedTime": "2024-03-27T14:58:55.934629Z", + "runId": "22d7d6a9-33b5-4565-8575-2f2ee24a06a1", + "status": "success" + }, + { + "groupNumber": 1, + "lastUpdateTime": "2024-03-27T15:01:05.766027Z", + "nodeId": "e4b1b524-4e77-4448-b1a9-01b80288c898", + "receivedTime": "2024-03-27T15:00:03.220273Z", + "runId": "56960929-ca32-463a-bc6e-c0a6cca4f89d", + "status": "success" + } + ], + "totalItems": 5 + } + ``` + + Each job run has a run ID. You can use the job run IDs to get information about each step of a job run. + + In this example, the run IDs are: + + - `"496f0d9a-f0be-4cb7-8cbb-2285b5c42045"` + - `"306d3a00-d483-4aa2-bb09-1cd8c91c15e8"` + - `"376226b9-f916-42a1-8620-a4636598c5e5"` + - `"22d7d6a9-33b5-4565-8575-2f2ee24a06a1"` + - `"56960929-ca32-463a-bc6e-c0a6cca4f89d"` + + + +## Get the job run step details for a run + +- Use the job run ID to get a list of steps executed during a job run: + + ```sh + chef-courier-cli state run list-steps --runId --profile + ``` + + ```json + { + "items": [ + { + "inputs": "", + "interpreterPath": "/hab/pkgs/chef-platform/shell-interpreter/0.1.3/20240318113204/bin/shell-interpreter", + "interpreterVersion": "", + "numAttempts": 1, + "outputs": "", + "reason": "", + "status": "success", + "stepNumber": 1 + } + ], + "totalItems": 1 + } + ``` + +## Debug Courier jobs + +You can also review the job step details by connecting to a node with SSH and checking the Courier Runner logs. + +For a Linux node: + +```sh +cd /hab/svc/courier-runner/logs +tail -f courier-log +``` + +For a Windows node: + +```powershell +cd C:\hab\svc\courier-runner\logs +gc .\courier-log -Wait +``` diff --git a/content/360/saas/get_started/node_cohort.md b/content/360/saas/get_started/node_cohort.md new file mode 100644 index 0000000000..07e3b63bd6 --- /dev/null +++ b/content/360/saas/get_started/node_cohort.md @@ -0,0 +1,58 @@ ++++ +title = "Create a node cohort" + +[menu.cloud] +title = "Create a node cohort" +identifier = "chef_cloud/360/get_started/cohort" +parent = "chef_cloud/360/get_started" +weight = 90 ++++ + +{{< readfile file="content/360/saas/reusable_text/md/node_cohort_overview.md" >}} + +## Prerequisites + +- [Override settings are defined]({{< relref "override_settings" >}}). + +## Create a node cohort + +To create a node cohort, follow these steps: + +1. Create a file named `node-cohort.json` that contains the skill assembly ID and the settings ID it should be associated to. + + ```json + { + "name": "node-cohort-mchef", + "description": "Description first cohort", + "settingId": "5b305ea5-c89b-4ac3-a471-60dadf4980ed", + "skillAssemblyId":"4ecbe415-838a-4446-abc1-9c57de9211d8" + } + ``` + +1. Create the node cohort: + + ```sh + chef-node-management-cli management cohort create-cohort --body-file node-cohort.json --profile + ``` + + ```json + { + "item": { + "cohortId": "86628101-0f31-48aa-b035-a8889232e568" + } + } + ``` + + The above command returns a response containing the `cohortId`. Save it for using during Node Enrollment. + +## Troubleshooting + +- Verify that the node cohort was created successfully: + + ```sh + chef-node-management-cli management cohort find-one-cohort --cohortId --profile + ``` + +## Next step + +- [Enroll Nodes]({{< relref "enroll_nodes.md" >}}). diff --git a/content/360/saas/get_started/override_settings.md b/content/360/saas/get_started/override_settings.md new file mode 100644 index 0000000000..3a6fbc4e7a --- /dev/null +++ b/content/360/saas/get_started/override_settings.md @@ -0,0 +1,55 @@ ++++ +title = "Create override settings" + +[menu.cloud] +title = "Create override settings" +identifier = "chef_cloud/360/get_started/override settings" +parent = "chef_cloud/360/get_started" +weight = 80 ++++ + +When you created the Courier Runner skill definition in the previous section, +it contained a base64-encoded TOML string in the value of `content` key. This TOML includes settings that can or should be overridden with settings for your Chef 360 Platform system. +When Node Management runs on a node, it executes Courier Runner using values in the TOML file that are set by values stored in the Courier Runner's default settings or the Courier Runner's override settings. + +## Prerequisites + +- [A skill assembly is defined]({{< relref "create_skill_assembly" >}}). + +## Create override settings + +Create node override settings for the Courier Runner and Gohai skills. + +1. Create a file named `node-override-setting.json` and paste in the following JSON: + + {{% readfile file="_vendor/github.com/chef/samples/cohorts/node-override-setting.json" highlight="json" %}} + + This JSON file creates settings for Courier Runner. + +1. Use the `create-setting` subcommand to create the override setting: + + ```sh + chef-node-management-cli management setting create-setting --body-file node-override-setting.json --profile + ``` + + which returns: + + ```json + { + "item": { + "settingId": "" + } + } + ``` + + Save the setting ID, you'll use it to create a node cohort. + +1. Verify that the setting was created. + + ```sh + chef-node-management-cli management setting find-one-setting --settingId --profile + ``` + +## Next step + +- [Create a node cohort]({{< relref "node_cohort.md" >}}) diff --git a/content/360/saas/get_started/register_node_agent.md b/content/360/saas/get_started/register_node_agent.md new file mode 100644 index 0000000000..09512f7478 --- /dev/null +++ b/content/360/saas/get_started/register_node_agent.md @@ -0,0 +1,61 @@ ++++ +title = "Register Node Management agent" + +[menu.cloud] +title = "Register Node Management Agent" +identifier = "chef_cloud/360/get_started/Register Node Management Agent" +parent = "chef_cloud/360/get_started" +weight = 50 ++++ + +The Node Management agent manages skills on a node. +You must define settings on the Node Management agent before defining skills and override settings that are installed on nodes. + +## Prerequisites + +- [CLIs are installed and registered]({{< relref "../get_started/install_cli" >}}). + +## Register the Node Management agent + +To register a Node Management agent, follow these steps: + +1. Create a file named `register-agent-skill.json` that contains the settings for Node Management agent to function: + + ```json + { + "bldrUrl": "", + "bldrChannel": "", + "bldrAuthToken": "", + "nodeCheckinInterval": , + "updateSkillMetadataInterval": , + "logLevel": "" + } + ``` + + Replace: + + - `` with the Chef Habitat Builder URL. Use `https://bldr.habitat.sh` for Chef's Habitat Builder, or the URL of your own Habitat Builder deployment. + - `` with the release channel from which to install the skills. For example, `stable`. + - `` with the authentication token for Habitat Builder. If you're using Chef's Habitat Builder, set this to an empty string. + - `` with the interval (in seconds) at which check-in occurs. Value starting from `3600` (1 hr). + - `` with the interval (in seconds) at which skill definitions will be updated. Value starting from `3600` (1 hr). + - ``: The logging level of the agent. For example, `debug`. + +1. Create the skill assembly: + + ```sh + chef-node-management-cli management skill update-agent --body-file register-agent-skill.json --profile + ``` + + It returns the following response: + + ```json + { + "code" : 200, + "message" : update-agent successful + } + ``` + +## Next step + +- [Create skill definitions]({{< relref "define_skills.md" >}}). diff --git a/content/360/saas/get_started/set_up.md b/content/360/saas/get_started/set_up.md new file mode 100644 index 0000000000..2e1cde7caf --- /dev/null +++ b/content/360/saas/get_started/set_up.md @@ -0,0 +1,58 @@ ++++ +title = "Set up your Chef 360 SaaS environment" + +[menu.cloud] +title = "Set up Chef 360 SaaS" +identifier = "chef_cloud/360/get_started/set_up" +parent = "chef_cloud/360/get_started" +weight = 30 ++++ + +This document describes how to login and configure Chef 360 SaaS, add users, and add a license. + +## Prerequisites + +- If you don't already have one, you'll need a [Chef 360 SaaS account](https://www.chef.io/products/chef-360-saas) before you can get started. +- Review the [system requirements]({{< relref "system_requirements" >}}). + +## Login + +After signing up for a Chef 360 SaaS account, you'll receive three emails with information for logging in and setting up your account. an email with your Progress Chef license key, an email to set your user password, and an email notifying you of the organization you've been added to and the role you've been given. + +To login and set your license, follow these steps: + +1. Open the link in the email titled _Set Password_. + +1. In the Chef 360 SaaS login page, enter your onetime password and a new replacement password. + + The login page shows a message indicating that your password was successfully set. + +1. Login using your new password and email address. + +1. In the **Welcome** page, select the tenant you're logging into and the **tenant-admin** role, then select **Proceed**. + + You are now logged into Chef 360 SaaS with the Tenant Admin role. + +## Add users + +To add a new user to Chef 360 SaaS, follow these steps: + +1. From the Chef 360 SaaS web user interface, select **Tenant Management**. + +1. In the left navigation menu, select **User Management**. + +1. Select **Invite User** on the right side of the User Management page. + +1. In the **Invite User** dialog, enter the user's email address and user role, then select **Send Invite**. + +The new user will receive an email with instructions for logging in and setting a password. + +## Troubleshooting + +### Setting your password failed + +If your login failed because you forgot your password or you missed the five minute window to set your password, you can reset it by following these steps: + +1. At your organization's login page (**`https://CUSTOMER_SUBDOMAIN.cloud.chef.io/app/hub`**), select **Forgot Password** and enter the email address you used sign up with Chef 360 SaaS. + +1. You'll receive an email with a link to reset your password. You have five minutes follow the link and create a new password. diff --git a/content/360/saas/get_started/system_requirements.md b/content/360/saas/get_started/system_requirements.md new file mode 100644 index 0000000000..0bc34fa415 --- /dev/null +++ b/content/360/saas/get_started/system_requirements.md @@ -0,0 +1,58 @@ ++++ +title = "Chef 360 SaaS system requirements" + +[menu.cloud] +title = "System requirements" +identifier = "chef_cloud/360/get_started/requirements" +parent = "chef_cloud/360/get_started" +weight = 20 ++++ + +## Node requirements + +This guide describes two methods of enrolling nodes, either with a Chef Infra cookbook or with single-node enrollment from Chef 360 SaaS. +See the node requirements for those methods in the following sections. + +For more information on these enrollment methods, see the node enrollment guide or the node enrollment documentation. + +### Cookbook-based enrollment + +Nodes enrolled with Chef 360 Platform using a Chef Infra cookbook have the following requirements: + +- Nodes must have Chef Infra Client installed. +- Nodes have a public DNS or public IP address that can be reached from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. +- Nodes must allow for outbound and inbound communication with +- Nodes can’t have localhost (127.0.0.1) as an IP address. +- You must have sudo privileges on the node. +- Note: Requires Chef Infra Server or running Chef Infra Client in zero mode. For SaaS, this requires Chef 360 SaaS Enterprise. + +### Chef 360 platform-based enrollment + +Nodes enrolled using single-node enrollment have the following requirements. + +Connection requirements: + +- Nodes must be accessible with SSH or WinRM from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. +- Nodes must have a public DNS or public IP address that can be reached from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. +- Nodes must allow for outbound and inbound communication with +- A node IP address can’t be localhost (127.0.0.1) +- A node CIDR address can’t be in the same range as the Chef 360 Platform services. The default CIDR range for Chef 360 Platform services is `10.244.0.0/16` or `10.96.0.0/12`. +- The node’s ports for RabbitMQ (31050) and the nginx API gateway (31000) must be open to Chef 360 Platform. Additionally, the Chef 360 Platform should allow inbound connections to these ports from the node. + +Nodes connected to with SSH have the following requirements: + +- Port 22 must be open. +- The user must have sudo privileges. +- The user must connect with an ed25519 or RSA(2048) login key without a passphrase. + +Nodes connected to with WinRM have the following requirements: + +- Ports 5985–5986 must be open. +- Configure WinRM by running the following: + + ```ps1 + winrm quickconfig # select Yes + winrm set winrm/config/service/Auth '@{Basic="true"}' + winrm set winrm/config/service '@{AllowUnencrypted="true"}' + netsh advfirewall firewall add rule name="WinRM-HTTP" dir=in localport=5985 protocol=TCP action=allow + ``` diff --git a/content/360/saas/reusable_text/index.md b/content/360/saas/reusable_text/index.md new file mode 100644 index 0000000000..7471a763f6 --- /dev/null +++ b/content/360/saas/reusable_text/index.md @@ -0,0 +1,11 @@ ++++ +title = 'Headless section' + +[[cascade]] + [cascade.build] + list = 'local' + publishResources = false + render = 'never' ++++ + + diff --git a/content/360/saas/reusable_text/json/enroll-node-linux-rsa.json b/content/360/saas/reusable_text/json/enroll-node-linux-rsa.json new file mode 100644 index 0000000000..2b67174e4e --- /dev/null +++ b/content/360/saas/reusable_text/json/enroll-node-linux-rsa.json @@ -0,0 +1,9 @@ +{ + "cohortId": "", + "url": "", + "sshCredentials": { + "username": "", + "key": "", + "port": + } +} diff --git a/content/360/saas/reusable_text/json/enroll-node-windows.json b/content/360/saas/reusable_text/json/enroll-node-windows.json new file mode 100644 index 0000000000..e59b226862 --- /dev/null +++ b/content/360/saas/reusable_text/json/enroll-node-windows.json @@ -0,0 +1,8 @@ +{ + "cohortId": "", + "url": "", + "winRMCredentials": { + "username": "", + "password": "" + } +} diff --git a/content/360/saas/reusable_text/md/clis_add_license.md b/content/360/saas/reusable_text/md/clis_add_license.md new file mode 100644 index 0000000000..89045c62f1 --- /dev/null +++ b/content/360/saas/reusable_text/md/clis_add_license.md @@ -0,0 +1,12 @@ + +Before you can use the Chef 360 Platform CLIs, you must add your license to your workstation. + +- To add a license, use the `license-management license load-license` command and your license key: + + ```sh + chef-platform-auth-cli license-management license load-license --body '{"licenseId":""}' --profile tenant-admin + ``` + + Replace `` with the license key you received in your email. + + After adding your license, `chef-platform-auth-cli` returns a success message. diff --git a/content/360/saas/reusable_text/md/clis_install_saas.md b/content/360/saas/reusable_text/md/clis_install_saas.md new file mode 100644 index 0000000000..616c41b7e1 --- /dev/null +++ b/content/360/saas/reusable_text/md/clis_install_saas.md @@ -0,0 +1,20 @@ + +Follow these steps to download and install the Chef 360 CLIs: + +1. From the Chef 360 SaaS home page, select **Download Centre**. + +1. From the **Download Centre** page, follow the instructions to download and install each CLI tool. + +1. After the CLIs are installed, run each CLI with the `--help` flag to verify that it's installed: + + - ```sh + chef-courier-cli --help + ``` + + - ```sh + chef-platform-auth-cli --help + ``` + + - ```sh + chef-node-management-cli --help + ``` diff --git a/content/360/saas/reusable_text/md/clis_verify_profiles.md b/content/360/saas/reusable_text/md/clis_verify_profiles.md new file mode 100644 index 0000000000..a1ae4565aa --- /dev/null +++ b/content/360/saas/reusable_text/md/clis_verify_profiles.md @@ -0,0 +1,42 @@ + +Use these commands to verify your profiles and credentials. + +1. List all your profiles with the `list-profile-names` subcommand. For example: + + ```sh + chef-platform-auth-cli list-profile-names + ``` + + The response is similar to the following: + + ```sh + List of available profile names: + 1. tenant1 + 2. default + ``` + + You can use `list-profile-names` subcommand with any of the Chef 360 Platform CLIs to get a list of your profiles. + +1. Get details of your default profile using the `get-default-profile` subcommand: + + ```sh + chef-platform-auth-cli get-default-profile + ``` + + The response is similar to the following: + + ```sh + Default profile: + + [default] + DeviceId = "ac:de:48:00:11:22-admin-chef-courier-cli" + Url = "http://tenant-1.dev-360.example.com" + OrgName = "Test OU1" + RoleName = "org-admin" + AccessKey = "FIT3SXM...YK4V05Y" + SecretKey = "Cwaygh4FqE2s...p9IE9YpzoGuX" + Cafile = "" + Insecure = true + ``` + + You can use `get-default-profile` subcommand with any of the Chef 360 Platform CLIs to get your default profile. diff --git a/content/360/saas/reusable_text/md/install_bash_completion.md b/content/360/saas/reusable_text/md/install_bash_completion.md new file mode 100644 index 0000000000..2d1debcd24 --- /dev/null +++ b/content/360/saas/reusable_text/md/install_bash_completion.md @@ -0,0 +1,51 @@ +Each Chef 360 Platform CLI has a `completion bash` subcommand. You must install the [bash-completion package](https://github.com/scop/bash-completion) to run these subcommands. + +To install and configure the bash-completion package, follow these steps: + +1. Install the bash-completion package. + + To install the bash-completion package on Linux systems, use the APT or Yum package manager: + + ```bash + sudo apt-get install bash-completion + ``` + + or + + ```bash + sudo yum install bash-completion + ``` + + To install the bash-completion package on macOS, use Homebrew: + + ```bash + brew install bash-completion + ``` + +1. Configure your Bash shell. + + To load the bash-completion package in every shell session by default, you must enable it in the `.bash_profile` or `.bashrc` file. + + To enable it on Linux systems, add the following lines to the `.bash_profile` or `.bashrc` file: + + ```bash + if [ -f /etc/bash_completion ] && ! shopt -oq posix; then + . /etc/bash_completion + fi + ``` + + To enable it on macOS, add the following lines to the `.bash_profile` or `.bashrc` file: + + ```bash + if [ -f $(brew --prefix)/etc/bash_completion ]; then + . $(brew --prefix)/etc/bash_completion + fi + ``` + + or + + ```bash + if [[ -r "$(brew --prefix)/etc/profile.d/bash_completion.sh" ]]; then + . "$(brew --prefix)/etc/profile.d/bash_completion.sh" + fi + ``` diff --git a/content/360/saas/reusable_text/md/node_cohort_overview.md b/content/360/saas/reusable_text/md/node_cohort_overview.md new file mode 100644 index 0000000000..59309d43bf --- /dev/null +++ b/content/360/saas/reusable_text/md/node_cohort_overview.md @@ -0,0 +1,3 @@ +A node cohort defines skills and settings installed on every node in a cohort. + +After you create a cohort, you assign nodes to the cohort during node enrollment, and Chef 360 Platform installs or removes the skills and settings on every node accordingly. diff --git a/content/360/saas/reusable_text/md/node_enrollment_status_node_id.md b/content/360/saas/reusable_text/md/node_enrollment_status_node_id.md new file mode 100644 index 0000000000..8547d75b29 --- /dev/null +++ b/content/360/saas/reusable_text/md/node_enrollment_status_node_id.md @@ -0,0 +1,23 @@ +You can get the node enrollment level of a node using the node ID and the `management node find-one-node` subcommand: + +```sh +chef-node-management-cli management node find-one-node --nodeId --profile +``` + +Once a node is successfully enrolled, the enrollment level is set to `enrolled`, otherwise it remains at `admitted`. + +```json +"enrollmentLevel": "enrolled" +``` + +You can also check the enrollment status for the individual steps: + +```sh +chef-node-management-cli status get-status --nodeId --profile +``` + +Each step should have a `success` status. + +```json +"status": "Success" +``` diff --git a/content/360/saas/reusable_text/md/skill_assembly_get_started.md b/content/360/saas/reusable_text/md/skill_assembly_get_started.md new file mode 100644 index 0000000000..11ef91ed9d --- /dev/null +++ b/content/360/saas/reusable_text/md/skill_assembly_get_started.md @@ -0,0 +1,23 @@ +1. Create a file named `skill-assembly.json` and paste in the following skill assembly definition: + + {{% readfile file="_vendor/github.com/chef/samples/cohorts/skill-assembly.json" highlight="json" %}} + + Replace each skill's version number with the version supported by the version of Chef 360 Platform that you're running. See the [Chef 360 Platform 1.2 release notes](https://docs.chef.io/360/1.2/release_notes) for the current supported skill versions. + +1. Create the skill assembly: + + ```sh + chef-node-management-cli management assembly create-assembly --body-file skill-assembly.json --profile + ``` + + The response is similar to the following: + + ```json + { + "item": { + "skillAssemblyId": "e2e66c8a-79ff-4bdc-a4cd-739c3f02f9e9" + } + } + ``` + + Save the value of `skillAssemblyId`, you will use it to create a node cohort. diff --git a/content/saas/_index.md b/content/saas/_index.md index 0f7ade8c66..57e5a7c1e9 100644 --- a/content/saas/_index.md +++ b/content/saas/_index.md @@ -6,10 +6,10 @@ draft = false product = ["saas"] [menu] - [menu.saas] + [menu.cloud] title = "Overview" - identifier = "chef_infra/Overview" - parent = "chef_saas" + identifier = "chef_cloud/saas/Overview" + parent = "chef_cloud/saas" weight = 10 +++ diff --git a/content/saas/get_started.md b/content/saas/get_started.md index 90aa3c09f8..0aeb9bbd7d 100644 --- a/content/saas/get_started.md +++ b/content/saas/get_started.md @@ -2,10 +2,10 @@ title = "Get Started with Chef SaaS" draft = false [menu] - [menu.saas] + [menu.cloud] title = "Get Started" - identifier = "chef_infra/Get Started with Chef SaaS" - parent = "chef_saas" + identifier = "chef_cloud/saas/Get Started with Chef SaaS" + parent = "chef_cloud/saas" weight = 20 +++ diff --git a/content/saas/opsworks_migration.md b/content/saas/opsworks_migration.md index 3df57ac3a6..9b317da767 100644 --- a/content/saas/opsworks_migration.md +++ b/content/saas/opsworks_migration.md @@ -2,10 +2,10 @@ title = "Migrate from AWS OpsWorks to Chef SaaS" draft = false [menu] - [menu.saas] + [menu.cloud] title = " AWS OpsWorks Migration" - identifier = "chef_infra/OpsWorks Migration" - parent = "chef_saas" + identifier = "chef_cloud/saas/OpsWorks Migration" + parent = "chef_cloud/saas" weight = 30 +++ diff --git a/content/saas/register_nodes.md b/content/saas/register_nodes.md index 02e0dfbf03..2f5811eb22 100644 --- a/content/saas/register_nodes.md +++ b/content/saas/register_nodes.md @@ -2,10 +2,10 @@ title = "Redirect existing nodes to Chef SaaS" draft = false [menu] - [menu.saas] + [menu.cloud] title = "Redirect nodes" - identifier = "chef_infra/Register Nodes to Chef SaaS Environment" - parent = "chef_saas" + identifier = "chef_cloud/saas/Register Nodes to Chef SaaS Environment" + parent = "chef_cloud/saas" weight = 50 +++ diff --git a/content/saas/sso.md b/content/saas/sso.md index d960477218..97b18ccb93 100644 --- a/content/saas/sso.md +++ b/content/saas/sso.md @@ -3,11 +3,11 @@ title = "Configure SSO for Chef SaaS" draft = false [menu] - [menu.saas] + [menu.cloud] title = "Configure SSO" - identifier = "chef_infra/Configure SSO" - parent = "chef_saas" + identifier = "chef_cloud/saas/Configure SSO" + parent = "chef_cloud/saas" weight = 40 +++ diff --git a/go.mod b/go.mod index a09206a305..766235df9c 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/chef/desktop-config/docs-chef-io v0.0.0-20240814044820-5af667d41a43 // indirect github.com/chef/effortless/docs-chef-io v0.0.0-20230711123605-c8beb79aba4f // indirect github.com/chef/license-service/docs-chef-io v0.0.0-20250120051510-ae1de80f4621 // indirect + github.com/chef/samples v0.0.0-20250304162216-b7bf3710b07e // indirect github.com/chef/supermarket/docs-chef-io v0.0.0-20241105172430-a362eded8f72 // indirect github.com/cowboy/jquery-hashchange v0.0.0-20100902193700-0310f3847f90 // indirect github.com/habitat-sh/habitat/components/docs-chef-io v0.0.0-20241227173243-de19b906a228 // indirect diff --git a/go.sum b/go.sum index dcff5a0df3..9a7af7272e 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/chef/effortless/docs-chef-io v0.0.0-20230711123605-c8beb79aba4f h1:6+ github.com/chef/effortless/docs-chef-io v0.0.0-20230711123605-c8beb79aba4f/go.mod h1:Lfq+HjwAQwUJ41EPTO/8qbI1oJb2i415fR28d2Ig9kc= github.com/chef/license-service/docs-chef-io v0.0.0-20250120051510-ae1de80f4621 h1:xhFjMLTM/newy2E4YVEZPE8Pfr7Z1yJOkby7BRDlbA8= github.com/chef/license-service/docs-chef-io v0.0.0-20250120051510-ae1de80f4621/go.mod h1:leNCF0KadV7zjm7YpVegNnbmWYUFXgaPKHP4tTDacos= +github.com/chef/samples v0.0.0-20250304162216-b7bf3710b07e h1:Eyntx13lbTXGobnPhPzsN3SuNTLb/6j4Fe5CseiCsLo= +github.com/chef/samples v0.0.0-20250304162216-b7bf3710b07e/go.mod h1:RiMNPQ6ddrNSgTOcBrYaEVicaP52xs9TQz4RA+XTreA= github.com/chef/supermarket/docs-chef-io v0.0.0-20241105172430-a362eded8f72 h1:mGnH8fxL69YfwoLP+mJP5fodAukQVf0A5lmF+7Cq/64= github.com/chef/supermarket/docs-chef-io v0.0.0-20241105172430-a362eded8f72/go.mod h1:D+9mmEZxCwpdhZ8LrEODBWMwMufmJUubSt5NlU/lLB4= github.com/cowboy/jquery-hashchange v0.0.0-20100902193700-0310f3847f90 h1:p/a5iSATj0OjrqJLX/YKxYdGXhZzW58yyyNIC4JY4S0= diff --git a/static/images/360/select-role.png b/static/images/360/select-role.png new file mode 100644 index 0000000000000000000000000000000000000000..d3845f92cc2da5c38b66ab9548577de95554d641 GIT binary patch literal 78538 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 literal 0 HcmV?d00001 diff --git a/static/images/360/setting-expiry-token.png b/static/images/360/setting-expiry-token.png new file mode 100644 index 0000000000000000000000000000000000000000..84a33c60a0119f24f5fafcd2fcce788d2701045b GIT binary patch literal 84341 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 literal 0 HcmV?d00001 From de04147f53df4b2428c259f823df8cc9d2524f1f Mon Sep 17 00:00:00 2001 From: Ian Maddaus Date: Mon, 10 Mar 2025 14:46:03 -0400 Subject: [PATCH 2/6] Update 360 content to match 1.2.1 docs Signed-off-by: Ian Maddaus --- .../saas/get_started/register_node_agent.md | 28 ++++++++++++++----- .../saas/get_started/system_requirements.md | 12 +++++++- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/content/360/saas/get_started/register_node_agent.md b/content/360/saas/get_started/register_node_agent.md index 09512f7478..167f827286 100644 --- a/content/360/saas/get_started/register_node_agent.md +++ b/content/360/saas/get_started/register_node_agent.md @@ -17,9 +17,9 @@ You must define settings on the Node Management agent before defining skills and ## Register the Node Management agent -To register a Node Management agent, follow these steps: +To register the Node Management agent, follow these steps: -1. Create a file named `register-agent-skill.json` that contains the settings for Node Management agent to function: +1. Create a file named `register-agent-skill.json` that defines the Node Management agent settings: ```json { @@ -34,17 +34,31 @@ To register a Node Management agent, follow these steps: Replace: - - `` with the Chef Habitat Builder URL. Use `https://bldr.habitat.sh` for Chef's Habitat Builder, or the URL of your own Habitat Builder deployment. - - `` with the release channel from which to install the skills. For example, `stable`. + - `` with the Chef Habitat Builder URL. Use `https://bldr.habitat.sh` for Chef's Habitat Builder or the URL of your own Habitat Builder deployment. + - `` with the release channel from which to install skills. For example, `stable`. - `` with the authentication token for Habitat Builder. If you're using Chef's Habitat Builder, set this to an empty string. - - `` with the interval (in seconds) at which check-in occurs. Value starting from `3600` (1 hr). - - `` with the interval (in seconds) at which skill definitions will be updated. Value starting from `3600` (1 hr). + - `` with the interval (in seconds) at which check-in occurs. Value starting from `3600` (1 hour). + - `` with the interval (in seconds) at which skill definitions are updated. Value starting from `3600` (1 hour). - ``: The logging level of the agent. For example, `debug`. + Supported log levels: + + `debug` + : Reports detailed information that can aid in identifying issues or debugging a workload. This includes the info, warn, and error logs. + + `info` + : Reports general information about the system's operations. + + `warn` + : Reports potential failures, but the operation can continue functioning for the time being. + + `error` + : Reports errors that prevent the execution of an operation. + 1. Create the skill assembly: ```sh - chef-node-management-cli management skill update-agent --body-file register-agent-skill.json --profile + chef-node-management-cli management skill update-agent --body-file register-agent-skill.json ``` It returns the following response: diff --git a/content/360/saas/get_started/system_requirements.md b/content/360/saas/get_started/system_requirements.md index 0bc34fa415..388e71b7c2 100644 --- a/content/360/saas/get_started/system_requirements.md +++ b/content/360/saas/get_started/system_requirements.md @@ -13,7 +13,17 @@ weight = 20 This guide describes two methods of enrolling nodes, either with a Chef Infra cookbook or with single-node enrollment from Chef 360 SaaS. See the node requirements for those methods in the following sections. -For more information on these enrollment methods, see the node enrollment guide or the node enrollment documentation. +### Ports + +Open the following default ports for outbound connections. + +| Port | Description | +|-------|------------------------------| +| 443 | HTTPS | +| 31050 | RabbitMQ AMQP/AMQP-TLS | +| 31000 | Nginx Reverse Proxy NodePort | +| 22 | SSH (optional) | +| 80 | HTTP (optional) | ### Cookbook-based enrollment From 245e1f0667604f9dc636cd781f878c0649c3ac06 Mon Sep 17 00:00:00 2001 From: Ian Maddaus Date: Mon, 10 Mar 2025 15:53:05 -0400 Subject: [PATCH 3/6] Corrections Signed-off-by: Ian Maddaus --- content/360/saas/_index.md | 8 ++++---- content/360/saas/get_started/_index.md | 4 ++-- content/360/saas/get_started/define_skills.md | 2 +- content/360/saas/get_started/enroll_nodes.md | 20 +++++++++---------- content/360/saas/get_started/install_cli.md | 20 +++++++++++-------- content/360/saas/get_started/jobs.md | 2 +- .../360/saas/get_started/override_settings.md | 2 +- content/360/saas/get_started/set_up.md | 4 ++++ .../saas/get_started/system_requirements.md | 6 +++--- .../reusable_text/md/node_cohort_overview.md | 2 +- .../md/skill_assembly_get_started.md | 1 - 11 files changed, 39 insertions(+), 32 deletions(-) diff --git a/content/360/saas/_index.md b/content/360/saas/_index.md index 70e47c7ebc..2455a4e29e 100644 --- a/content/360/saas/_index.md +++ b/content/360/saas/_index.md @@ -15,13 +15,13 @@ weight = 10 Chef 360 SaaS focuses on job orchestration and node management in the cloud to complete your DevOPS journeys whenever, wherever, and however a business scenario requires. Chef 360 SaaS is hosted, maintained, and upgraded by Chef allowing you to focus on your workflows. -**Whenever**: The Chef 360 SaaS Platform provides real-time observability of the changing infrastructure environment through scheduled actions, continuous scanning or immediate “execute-once" semantics. +**Whenever**: Chef 360 SaaS provides real-time observability of the changing infrastructure environment through scheduled actions, continuous scanning or immediate “execute-once" semantics. -**Wherever**: The Chef 360 SaaS Platform operates across hybrid environments from on-premises data centers through to all major public clouds, and secures the wide variety of platforms and resources supported by Chef. +**Wherever**: Chef 360 SaaS operates across hybrid environments from on-premises data centers through to all major public clouds, and secures the wide variety of platforms and resources supported by Chef. -**Whatever**: The Chef 360 SaaS Platform enables DevOps and security engineering teams—whether they follow ITIL or ChatOps—to leverage the native JSON syntax or use one of several, extensible infrastructure-as-code DSLs. +**Whatever**: Chef 360 SaaS enables DevOps and security engineering teams—whether they follow ITIL or ChatOps—to leverage the native JSON syntax or use one of several, extensible infrastructure-as-code DSLs. -The Chef 360 SaaS Platform has a workflow engine to execute varied jobs in compliance and infrastructure management: +Chef 360 SaaS has a workflow engine to execute varied jobs in compliance and infrastructure management: - Regularly scan, audit, and remediate infrastructure, protecting your fleet with certified industry compliance profiles like CIS, SOC2, and CSPM. - Create composable jobs quickly using shell scripting and out-of-the-box skills to develop full playbooks, capable of coordinating the other DevOps IaC tools you own. diff --git a/content/360/saas/get_started/_index.md b/content/360/saas/get_started/_index.md index 9902d2dc12..45d787fcba 100644 --- a/content/360/saas/get_started/_index.md +++ b/content/360/saas/get_started/_index.md @@ -1,5 +1,5 @@ +++ -title = "Get started with Chef 360 Platform on-prem" +title = "Get started with Chef 360 SaaS" linkTitle = "Get started" [menu.cloud] @@ -9,7 +9,7 @@ parent = "chef_cloud/360/get_started" weight = 10 +++ -This section provides quickstart guides for getting started with Chef 360 Platform and its tools. +This section provides quickstart guides for getting started with Chef 360 SaaS and its tools. ## Get started guides diff --git a/content/360/saas/get_started/define_skills.md b/content/360/saas/get_started/define_skills.md index f070c0bb38..c5dd6f025e 100644 --- a/content/360/saas/get_started/define_skills.md +++ b/content/360/saas/get_started/define_skills.md @@ -20,7 +20,7 @@ A skill is an agent that gives you the ability to perform actions on a node to a ## Create skill definitions -The following Chef 360 Platform skills are required or recommended for managing nodes, running actions, and returning action results: +The following Chef 360 skills are required or recommended for managing nodes, running actions, and returning action results: - Courier Runner skill - Gohai skill diff --git a/content/360/saas/get_started/enroll_nodes.md b/content/360/saas/get_started/enroll_nodes.md index b7349b98ed..6d7a380a5c 100644 --- a/content/360/saas/get_started/enroll_nodes.md +++ b/content/360/saas/get_started/enroll_nodes.md @@ -8,7 +8,7 @@ parent = "chef_cloud/360/get_started" weight = 100 +++ -Node enrollment brings nodes under management by Chef 360 Platform. +Node enrollment brings nodes under management by Chef 360 SaaS. This document demonstrates two different methods of node enrollment: @@ -17,7 +17,7 @@ This document demonstrates two different methods of node enrollment: {{< note >}} -This version of Chef 360 Platform doesn't support node re-enrollment. +This version of Chef 360 SaaS doesn't support node re-enrollment. {{< /note >}} @@ -32,7 +32,7 @@ Review the [node requirements]({{< relref "system_requirements#node-requirements ## Single-node enrollment Single-node enrollment enrolls nodes from the server side. -With this method, you define connection and configuration details and push them up to Chef 360 Platform, which connects to each node and installs Chef Habitat, Chef Node Management, and any skills or agents assigned to a node cohort. +With this method, you define connection and configuration details and push them up to Chef 360 SaaS, which connects to each node and installs Chef Habitat, Chef Node Management, and any skills or agents assigned to a node cohort. ### Enroll Linux nodes @@ -120,7 +120,7 @@ To enroll a Windows node, follow these steps: ## Cookbook-based enrollment -With cookbook-based enrollment, you enroll nodes from the client side by uploading a [cookbook](https://docs.chef.io/cookbooks/) with enrollment settings to Chef Infra Server and then Chef Infra Client enrolls the node with Chef 360 Platform. +With cookbook-based enrollment, you enroll nodes from the client side by uploading a [cookbook](https://docs.chef.io/cookbooks/) with enrollment settings to Chef Infra Server and then Chef Infra Client enrolls the node with Chef 360 SaaS. ### Enroll nodes @@ -168,15 +168,15 @@ To configure the cookbooks and define enrollment settings, follow these steps: Replace: - - `` with the fully qualified domain name (FQDN) for your Chef 360 Platform deployment. + - `` with the fully qualified domain name (FQDN) for your Chef 360 SaaS deployment. - `` with either `full` or `partial` depending on the form of enrollment. Use `full` unless you must `partial`. - - `` with the API port configured in Chef 360 Platform. The default value is `31000`. - - `` with an access key for secure communication with Chef 360 Platform. Store securely using an [encrypted Chef data bag](https://docs.chef.io/data_bags/) or a [secrets manager](https://docs.chef.io/infra_language/secrets/). - - `` with a secret key for secure communication with Chef 360 Platform. Store securely using an [encrypted Chef data bag](https://docs.chef.io/data_bags/) or a [secrets manager](https://docs.chef.io/infra_language/secrets/). + - `` with the API port configured in Chef 360 SaaS. The default value is `31000`. + - `` with an access key for secure communication with Chef 360 SaaS. Store securely using an [encrypted Chef data bag](https://docs.chef.io/data_bags/) or a [secrets manager](https://docs.chef.io/infra_language/secrets/). + - `` with a secret key for secure communication with Chef 360 SaaS. Store securely using an [encrypted Chef data bag](https://docs.chef.io/data_bags/) or a [secrets manager](https://docs.chef.io/infra_language/secrets/). - `` with a valid cohort UUID. The cohort defines all skills and settings installed on the node. - `` with the URL of the Chef Habitat Builder used by your organization. Default value: `https://bldr.habitat.sh` - `` with a temporary working directory where all required builds are downloaded. Specify a valid path based on the OS. Default value: `/tmp`. - - `` with `true` or `false`. If `true`, Chef 360 Platform checks for the latest skill versions and installs them if found. Default value: `false`. + - `` with `true` or `false`. If `true`, Chef 360 SaaS checks for the latest skill versions and installs them if found. Default value: `false`. 1. Push the wrapper cookbook or policy to the Chef Infra Server. @@ -195,7 +195,7 @@ To configure the cookbooks and define enrollment settings, follow these steps: 1. Include the wrapper cookbook in your node's run-list by adding it to a role or Policyfile. See the [run-list](https://docs.chef.io/run_lists/) and [role](https://docs.chef.io/roles/#manage-roles) documentation for more information. - The next time Chef Infra Client runs, it executes the `node_management_enroll` resource and the node is enrolled with Chef 360 Platform. + The next time Chef Infra Client runs, it executes the `node_management_enroll` resource and the node is enrolled with Chef 360 SaaS. ## Check the node enrollment status diff --git a/content/360/saas/get_started/install_cli.md b/content/360/saas/get_started/install_cli.md index abb3756959..71e10bd1b5 100644 --- a/content/360/saas/get_started/install_cli.md +++ b/content/360/saas/get_started/install_cli.md @@ -10,7 +10,7 @@ parent = "chef_cloud/360/get_started" weight = 40 +++ -This page documents how to download and install the Chef 360 Platform CLIs and register your workstation with your Chef 360 Platform deployment. +This page documents how to download and install the Chef 360 Platform CLIs and register your workstation with your Chef 360 SaaS deployment. ## Prerequisites @@ -73,7 +73,7 @@ To create a profile, follow these steps: {{< note >}} - If you've configured Chef 360 Platform with a system-generated or custom certificate in the API/UI settings, use the following CLI arguments: + If you've configured Chef 360 SaaS with a system-generated or custom certificate in the API/UI settings, use the following CLI arguments: - If you don't have the root certificate authority, use the `--insecure` flag. This flag skips certificate validation. - If have the root certificate authority present, use the `--cafile ` flag. @@ -86,7 +86,7 @@ To create a profile, follow these steps: - `` with a profile name for the role that this profile will use. For example, add the `courier-operator` profile name for the `courier-operator` role. - `` with the tenant URL, for example `https://chef360.example.com:31000`. - The CLI responds with an authorization code that includes a link to log into Chef 360 Platform. + The CLI responds with an authorization code that includes a link to log into Chef 360 SaaS. ```sh Device Id : ac:de:48:00:11:22-admin-chef-courier-cli @@ -106,19 +106,19 @@ To create a profile, follow these steps: 1. Select the organization and role you would like to link to this profile and select **Submit**. - {{< figure src="/images/360/select-role.png" width="500px" alt="Chef 360 Platform organization and role selection screen." >}} + {{< figure src="/images/360/select-role.png" width="500px" alt="Chef 360 SaaS organization and role selection screen." >}} -1. On the **Device Authorization** screen, Chef 360 Platform shows your OAuth code and you can select an expiration date for your session. +1. On the **Device Authorization** screen, Chef 360 SaaS shows your OAuth code and you can select an expiration date for your session. - Chef 360 Platform automatically refreshes your access token up to this expiration date. + Chef 360 SaaS automatically refreshes your access token up to this expiration date. After entering this information, select **Authorize**. - {{< figure src="/images/360/setting-expiry-token.png" alt="Chef 360 Platform device authorization screen with OAuth token and expiration date." width="500px">}} + {{< figure src="/images/360/setting-expiry-token.png" alt="Chef 360 SaaS device authorization screen with OAuth token and expiration date." width="500px">}} 1. Return to your terminal and enter `y` to continue. - The CLI displays your device profile and your workstation is authorized to access Chef 360 Platform services. + The CLI displays your device profile and your workstation is authorized to access Chef 360 SaaS services. ```sh Is the device authorised? (y or n) @@ -159,6 +159,10 @@ To create a profile, follow these steps: 1. Repeat this procedure so that you have separate profiles for the Node Manager and Courier Operator roles. +## Additional information + +- [Chef 360 CLI reference documentation](https://docs.chef.io/360/1.2/reference/cli/) + ## Next step - [Register the Node Management agent]({{< relref "register_node_agent.md" >}}). diff --git a/content/360/saas/get_started/jobs.md b/content/360/saas/get_started/jobs.md index 79df6a43f8..46efe89d58 100644 --- a/content/360/saas/get_started/jobs.md +++ b/content/360/saas/get_started/jobs.md @@ -29,7 +29,7 @@ This job template creates a job that's executed one node, it runs immediately, a ## Create the job -When you add the job to Chef 360 Platform, the Courier Dispatcher sends the job definition to the Courier Runner on the specified node which determines when and how to run the job. +When you add the job to Chef 360 SaaS, the Courier Dispatcher sends the job definition to the Courier Runner on the specified node which determines when and how to run the job. You can submit a job definition using a JSON, YAML, or TOML file. The default format is JSON. - Add the job run using the job template file: diff --git a/content/360/saas/get_started/override_settings.md b/content/360/saas/get_started/override_settings.md index 3a6fbc4e7a..bc98f6034a 100644 --- a/content/360/saas/get_started/override_settings.md +++ b/content/360/saas/get_started/override_settings.md @@ -9,7 +9,7 @@ weight = 80 +++ When you created the Courier Runner skill definition in the previous section, -it contained a base64-encoded TOML string in the value of `content` key. This TOML includes settings that can or should be overridden with settings for your Chef 360 Platform system. +it contained a base64-encoded TOML string in the value of `content` key. This TOML includes settings that can or should be overridden with settings for your Chef 360 SaaS system. When Node Management runs on a node, it executes Courier Runner using values in the TOML file that are set by values stored in the Courier Runner's default settings or the Courier Runner's override settings. ## Prerequisites diff --git a/content/360/saas/get_started/set_up.md b/content/360/saas/get_started/set_up.md index 2e1cde7caf..5da08ea112 100644 --- a/content/360/saas/get_started/set_up.md +++ b/content/360/saas/get_started/set_up.md @@ -56,3 +56,7 @@ If your login failed because you forgot your password or you missed the five min 1. At your organization's login page (**`https://CUSTOMER_SUBDOMAIN.cloud.chef.io/app/hub`**), select **Forgot Password** and enter the email address you used sign up with Chef 360 SaaS. 1. You'll receive an email with a link to reset your password. You have five minutes follow the link and create a new password. + +## Next step + +- [Install Chef 360 CLIs]({{< relref "install_cli" >}}) diff --git a/content/360/saas/get_started/system_requirements.md b/content/360/saas/get_started/system_requirements.md index 388e71b7c2..a39d27443d 100644 --- a/content/360/saas/get_started/system_requirements.md +++ b/content/360/saas/get_started/system_requirements.md @@ -27,7 +27,7 @@ Open the following default ports for outbound connections. ### Cookbook-based enrollment -Nodes enrolled with Chef 360 Platform using a Chef Infra cookbook have the following requirements: +Nodes enrolled with Chef 360 SaaS using a Chef Infra cookbook have the following requirements: - Nodes must have Chef Infra Client installed. - Nodes have a public DNS or public IP address that can be reached from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. @@ -46,8 +46,8 @@ Connection requirements: - Nodes must have a public DNS or public IP address that can be reached from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. - Nodes must allow for outbound and inbound communication with - A node IP address can’t be localhost (127.0.0.1) -- A node CIDR address can’t be in the same range as the Chef 360 Platform services. The default CIDR range for Chef 360 Platform services is `10.244.0.0/16` or `10.96.0.0/12`. -- The node’s ports for RabbitMQ (31050) and the nginx API gateway (31000) must be open to Chef 360 Platform. Additionally, the Chef 360 Platform should allow inbound connections to these ports from the node. +- A node CIDR address can’t be in the same range as the Chef 360 SaaS services. The default CIDR range for Chef 360 SaaS services is `10.244.0.0/16` or `10.96.0.0/12`. +- The node’s ports for RabbitMQ (31050) and the nginx API gateway (31000) must be open to Chef 360 SaaS. Additionally, the Chef 360 SaaS should allow inbound connections to these ports from the node. Nodes connected to with SSH have the following requirements: diff --git a/content/360/saas/reusable_text/md/node_cohort_overview.md b/content/360/saas/reusable_text/md/node_cohort_overview.md index 59309d43bf..c18eb45893 100644 --- a/content/360/saas/reusable_text/md/node_cohort_overview.md +++ b/content/360/saas/reusable_text/md/node_cohort_overview.md @@ -1,3 +1,3 @@ A node cohort defines skills and settings installed on every node in a cohort. -After you create a cohort, you assign nodes to the cohort during node enrollment, and Chef 360 Platform installs or removes the skills and settings on every node accordingly. +After you create a cohort, you assign nodes to the cohort during node enrollment and Chef 360 SaaS installs or removes the skills and settings on every node accordingly. diff --git a/content/360/saas/reusable_text/md/skill_assembly_get_started.md b/content/360/saas/reusable_text/md/skill_assembly_get_started.md index 11ef91ed9d..77637a3797 100644 --- a/content/360/saas/reusable_text/md/skill_assembly_get_started.md +++ b/content/360/saas/reusable_text/md/skill_assembly_get_started.md @@ -2,7 +2,6 @@ {{% readfile file="_vendor/github.com/chef/samples/cohorts/skill-assembly.json" highlight="json" %}} - Replace each skill's version number with the version supported by the version of Chef 360 Platform that you're running. See the [Chef 360 Platform 1.2 release notes](https://docs.chef.io/360/1.2/release_notes) for the current supported skill versions. 1. Create the skill assembly: From adf2269482d4585016afecd8207bbcb4de95ad51 Mon Sep 17 00:00:00 2001 From: Ian Maddaus Date: Mon, 10 Mar 2025 15:57:04 -0400 Subject: [PATCH 4/6] Lint fix Signed-off-by: Ian Maddaus --- content/360/saas/_index.md | 6 +++--- content/360/saas/get_started/override_settings.md | 2 +- content/360/saas/get_started/system_requirements.md | 12 ++++++------ .../reusable_text/md/skill_assembly_get_started.md | 1 - 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/content/360/saas/_index.md b/content/360/saas/_index.md index 2455a4e29e..cd1de9def9 100644 --- a/content/360/saas/_index.md +++ b/content/360/saas/_index.md @@ -15,18 +15,18 @@ weight = 10 Chef 360 SaaS focuses on job orchestration and node management in the cloud to complete your DevOPS journeys whenever, wherever, and however a business scenario requires. Chef 360 SaaS is hosted, maintained, and upgraded by Chef allowing you to focus on your workflows. -**Whenever**: Chef 360 SaaS provides real-time observability of the changing infrastructure environment through scheduled actions, continuous scanning or immediate “execute-once" semantics. +**Whenever**: Chef 360 SaaS provides real-time observability of the changing infrastructure environment through scheduled actions, continuous scanning or immediate "execute-once" semantics. **Wherever**: Chef 360 SaaS operates across hybrid environments from on-premises data centers through to all major public clouds, and secures the wide variety of platforms and resources supported by Chef. -**Whatever**: Chef 360 SaaS enables DevOps and security engineering teams—whether they follow ITIL or ChatOps—to leverage the native JSON syntax or use one of several, extensible infrastructure-as-code DSLs. +**Whatever**: Chef 360 SaaS enables DevOps and security engineering teams--whether they follow ITIL or ChatOps--to leverage the native JSON syntax or use one of several, extensible infrastructure-as-code DSLs. Chef 360 SaaS has a workflow engine to execute varied jobs in compliance and infrastructure management: - Regularly scan, audit, and remediate infrastructure, protecting your fleet with certified industry compliance profiles like CIS, SOC2, and CSPM. - Create composable jobs quickly using shell scripting and out-of-the-box skills to develop full playbooks, capable of coordinating the other DevOps IaC tools you own. - Safely build, package, and deploy applications from a fully cloud-native, zero-trust platform in conjunction with Chef Habitat. -- Discover assets effortlessly from existing Chef environments, other Progress products like What’s-Up-Gold, and even your own CMDB and monitoring solutions. +- Discover assets effortlessly from existing Chef environments, other Progress products like What's-Up-Gold, and even your own CMDB and monitoring solutions. - Leverage an open partner ecosystem with Chef premium content and content from thought leaders such as OSL and MITRE, and easily extensible formats which require no special knowledge. ## Additional guides diff --git a/content/360/saas/get_started/override_settings.md b/content/360/saas/get_started/override_settings.md index bc98f6034a..fb5b279e86 100644 --- a/content/360/saas/get_started/override_settings.md +++ b/content/360/saas/get_started/override_settings.md @@ -38,7 +38,7 @@ Create node override settings for the Courier Runner and Gohai skills. { "item": { "settingId": "" - } + } } ``` diff --git a/content/360/saas/get_started/system_requirements.md b/content/360/saas/get_started/system_requirements.md index a39d27443d..8a5a77a7c7 100644 --- a/content/360/saas/get_started/system_requirements.md +++ b/content/360/saas/get_started/system_requirements.md @@ -32,11 +32,11 @@ Nodes enrolled with Chef 360 SaaS using a Chef Infra cookbook have the following - Nodes must have Chef Infra Client installed. - Nodes have a public DNS or public IP address that can be reached from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. - Nodes must allow for outbound and inbound communication with -- Nodes can’t have localhost (127.0.0.1) as an IP address. +- Nodes can't have localhost (127.0.0.1) as an IP address. - You must have sudo privileges on the node. - Note: Requires Chef Infra Server or running Chef Infra Client in zero mode. For SaaS, this requires Chef 360 SaaS Enterprise. -### Chef 360 platform-based enrollment +### Chef 360 SaaS enrollment Nodes enrolled using single-node enrollment have the following requirements. @@ -45,9 +45,9 @@ Connection requirements: - Nodes must be accessible with SSH or WinRM from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. - Nodes must have a public DNS or public IP address that can be reached from `https://CUSTOMER_SUBDOMAIN.cloud.chef.io`. - Nodes must allow for outbound and inbound communication with -- A node IP address can’t be localhost (127.0.0.1) -- A node CIDR address can’t be in the same range as the Chef 360 SaaS services. The default CIDR range for Chef 360 SaaS services is `10.244.0.0/16` or `10.96.0.0/12`. -- The node’s ports for RabbitMQ (31050) and the nginx API gateway (31000) must be open to Chef 360 SaaS. Additionally, the Chef 360 SaaS should allow inbound connections to these ports from the node. +- A node IP address can't be localhost (127.0.0.1) +- A node CIDR address can't be in the same range as the Chef 360 SaaS services. The default CIDR range for Chef 360 SaaS services is `10.244.0.0/16` or `10.96.0.0/12`. +- The node's ports for RabbitMQ (31050) and the nginx API gateway (31000) must be open to Chef 360 SaaS. Nodes connected to with SSH have the following requirements: @@ -57,7 +57,7 @@ Nodes connected to with SSH have the following requirements: Nodes connected to with WinRM have the following requirements: -- Ports 5985–5986 must be open. +- Ports 5985 and 5986 must be open. - Configure WinRM by running the following: ```ps1 diff --git a/content/360/saas/reusable_text/md/skill_assembly_get_started.md b/content/360/saas/reusable_text/md/skill_assembly_get_started.md index 77637a3797..a892e20cf1 100644 --- a/content/360/saas/reusable_text/md/skill_assembly_get_started.md +++ b/content/360/saas/reusable_text/md/skill_assembly_get_started.md @@ -2,7 +2,6 @@ {{% readfile file="_vendor/github.com/chef/samples/cohorts/skill-assembly.json" highlight="json" %}} - 1. Create the skill assembly: ```sh From dc5dfccf8050ddc7577d012d4fd6cce49d51ccd4 Mon Sep 17 00:00:00 2001 From: Ian Maddaus Date: Mon, 10 Mar 2025 16:10:11 -0400 Subject: [PATCH 5/6] Update node requirements Signed-off-by: Ian Maddaus --- content/360/saas/get_started/system_requirements.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/content/360/saas/get_started/system_requirements.md b/content/360/saas/get_started/system_requirements.md index 8a5a77a7c7..f00f3eb50d 100644 --- a/content/360/saas/get_started/system_requirements.md +++ b/content/360/saas/get_started/system_requirements.md @@ -65,4 +65,14 @@ Nodes connected to with WinRM have the following requirements: winrm set winrm/config/service/Auth '@{Basic="true"}' winrm set winrm/config/service '@{AllowUnencrypted="true"}' netsh advfirewall firewall add rule name="WinRM-HTTP" dir=in localport=5985 protocol=TCP action=allow + netsh advfirewall firewall add rule name="WinRM-HTTPS" dir=in localport=5986 protocol=TCP action=allow ``` + +### Skill requirements + +Chef 360 Platform skills are supported on the following platforms. + +| OS | Architecture | Version | +| ------- | ------------ | ----------------------------- | +| Linux | x86_64 | Kernel 2.6.32 or later | +| Windows | x86_64 | Windows Server 2019 and later | From 400af8f8f1e5124040aab4f6d552f72d8c3955f5 Mon Sep 17 00:00:00 2001 From: Ian Maddaus Date: Mon, 10 Mar 2025 16:17:54 -0400 Subject: [PATCH 6/6] Minor fix Signed-off-by: Ian Maddaus --- config/_default/menu.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/_default/menu.toml b/config/_default/menu.toml index 21a48e7295..40db08d6f4 100644 --- a/config/_default/menu.toml +++ b/config/_default/menu.toml @@ -695,7 +695,7 @@ identifier = "chef_cloud" parent = "chef_cloud/360" [[cloud]] - title = "Chef Saas" + title = "Chef SaaS" identifier = "chef_cloud/saas" parent = "chef_cloud"