├── .gitignore ├── CODEOWNERS ├── LICENSE ├── Makefile ├── README.md ├── ROADMAP.md ├── apis ├── DataFlowNodes_updated.png ├── README.md ├── how.md └── puppet-db-queries-pql.md ├── coding-best-practice ├── data-separation-using-hiera.md ├── handling-sensitive-data.md ├── hiera-hierarchy-design.md ├── roles-and-profiles.md └── style-and-naming-conventions.md ├── declarative ├── README.md ├── examples │ ├── .gitignore │ ├── Makefile │ ├── declarative.sqlite │ ├── hello.c │ └── var.pp ├── idempotence │ ├── README.md │ └── exec-resources.md └── type-title-namevar.md ├── links-to-html.lua ├── pam ├── install-cd4pe.md ├── install-comply.md └── kubernetes.md ├── plans ├── basic-plan-writing.md ├── composition-of-plans.md ├── dynamic-target-manipulation.md ├── error-handling-in-plans.md └── returning-data-from-plans.md ├── puppet-enterprise ├── installing-pe.md ├── macro-architecture.md └── micro-architecture │ ├── README.md │ ├── ace-server.md │ ├── certificate-authority.md │ ├── code-manager.md │ ├── console-services.md │ ├── file-sync.md │ ├── orchestration-services.md │ ├── postgresql.md │ ├── puppet-db.md │ ├── puppet-server.md │ ├── pxp.md │ └── rbac.md ├── puppet-ruby ├── custom-facts.md ├── custom-functions.md ├── custom-hiera-backends.md ├── custom-report-processors.md ├── puppet-faces.md ├── rspec-puppet-testing.md ├── testing-using-litmus.md └── types-and-providers.md ├── puppet.xml ├── puppet ├── conditional-logic.md ├── data-types.md ├── defined-types.md ├── lambdas.md ├── puppet-language-functions.md ├── ral.md ├── relationships-and-ordering.md ├── resource-type-syntax.md └── variables-and-scope.md ├── ruby ├── README.md ├── exploring-ruby-with-pry.md └── variables-and-scope.md ├── style.css ├── tasks ├── passing-parameters-powershell.md ├── passing-parameters.md ├── returning-dtata-from-tasks.md └── secure-code-practices.md └── workflow ├── custom-deployment-policies.md ├── dev-practices-for-ops.md ├── git-workflow-r10k.md └── workflows-using-cd4pe.md /.gitignore: -------------------------------------------------------------------------------- 1 | site/ 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # set ownership to the Professional Services team 2 | * @puppetlabs/professional-services 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Make document 2 | 3 | PANDOC = pandoc -s --css=/style.css -f markdown --highlight-style=tango --syntax-definition=puppet.xml 4 | TOHTML = $(PANDOC) -t html --lua-filter=links-to-html.lua 5 | 6 | SOURCES := $(shell find . -type f -name \*.md) 7 | TARGETS := $(subst README,index,$(patsubst %.md,site/%.html,$(SOURCES))) 8 | 9 | all: html 10 | site: 11 | mkdir -p $(dir $(TARGETS)) 12 | cp style.css site/ 13 | 14 | preview: html 15 | cd site/ && python -m SimpleHTTPServer 16 | html: site $(TARGETS) 17 | 18 | .PHONY: clean 19 | clean: 20 | rm -rf -- site 21 | 22 | site/index.html : README.md 23 | $(TOHTML) -t html -o $@ $< 24 | site/%/index.html : %/README.md 25 | $(TOHTML) -t html -o $@ $< 26 | site/%.html : %.md 27 | $(TOHTML) -t html -o $@ $< 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Puppet Language 2 | 3 | ## Language constructs 4 | 5 | - [Resource type syntax](puppet/resource-type-syntax.md) 6 | - [Conditional logic](puppet/conditional-logic.md) 7 | - [Variables and scope](puppet/variables-and-scope.md) 8 | - [Data types](puppet/data-types.md) 9 | - [Defined types](puppet/defined-types.md) 10 | - [Advanced function usage (e.g. functions that accept lambdas)](puppet/lambdas.md) 11 | - [Puppet-language functions](puppet/puppet-language-functions.md) 12 | - [Relationships and ordering](puppet/relationships-and-ordering.md) 13 | 14 | ## [Declarative coding concepts](declarative/) 15 | 16 | - [Resource idempotence](declarative/idempotence/) 17 | - [The type, title and namevar of a resource](declarative/type-title-namevar.md) 18 | - [The types and providers abstraction layer](puppet/ral.md) 19 | - [Idempotent exec resources](declarative/idempotence/exec-resources.md) 20 | 21 | ## Tasks 22 | 23 | - [Passing parameters](tasks/passing-parameters.md) 24 | - [Passing parameters using powershell](tasks/passing-parameters-powershell.md) 25 | - [Returning data from tasks](tasks/returning-dtata-from-tasks.md) 26 | - [Secure coding practices](tasks/secure-code-practices.md) 27 | 28 | ## Plans 29 | 30 | - [Basic plan writing](plans/basic-plan-writing.md) 31 | - [Error handling in plans](plans/error-handling-in-plans.md) 32 | - [Dynamic target manipulation (i.e. changing the targeted nodes using in-plan logic)](plans/dynamic-target-manipulation.md) 33 | - [Returning data from a plan](plans/returning-data-from-plans.md) 34 | - [Composition of plans](plans/composition-of-plans.md) (plans that run plans) 35 | 36 | # Ruby 37 | 38 | ## [Ruby basics](ruby/README.md) 39 | 40 | - Debugging & [exploring ruby using pry](ruby/exploring-ruby-with-pry.md) 41 | - Conditional logic 42 | - [Variables and scope](ruby/variables-and-scope.md) 43 | - Data types 44 | - Object-orientated programming 45 | 46 | ## Puppet-specific ruby 47 | 48 | - [Custom facts](puppet-ruby/custom-facts.md) 49 | - [Custom functions](puppet-ruby/custom-functions.md) 50 | - [Rspec-puppet and testing](puppet-ruby/rspec-puppet-testing.md) 51 | - [Testing using Litmus](puppet-ruby/testing-using-litmus.md) 52 | - [Types and providers](puppet-ruby/types-and-providers.md) 53 | - [Custom report processors](puppet-ruby/custom-report-processors.md) 54 | - [Custom hiera backends](puppet-ruby/custom-hiera-backends.md) 55 | - [Puppet faces?](puppet-ruby/puppet-faces.md) 56 | 57 | # Puppet Enterprise 58 | 59 | ## Architecture 60 | 61 | - [Installing PE](puppet-enterprise/installing-pe.md) 62 | - [Macro architecture](puppet-enterprise/macro-architecture.md) i.e. compilers, primary, secondary 63 | - [Micro architecture](puppet-enterprise/micro-architecture/), what services do, how they are configured, what are their dependencies, are they stateful or stateless, can they be load-balanced, how are they made HA? 64 | - [ACE-Server](puppet-enterprise/micro-architecture/ace-server.md) 65 | - [Orchestration-services](puppet-enterprise/micro-architecture/orchestration-services.md) 66 | - [PXP](puppet-enterprise/micro-architecture/pxp.md) 67 | - [Puppetserver](puppet-enterprise/micro-architecture/puppet-server.md) 68 | - [Console-services](puppet-enterprise/micro-architecture/console-services.md) 69 | - [RBAC](puppet-enterprise/micro-architecture/rbac.md) 70 | - [Certificate authority](puppet-enterprise/micro-architecture/certificate-authority.md) 71 | - [Puppetdb](puppet-enterprise/micro-architecture/puppet-db.md) 72 | - [Postgresql](puppet-enterprise/micro-architecture/postgresql.md) 73 | - [Code manager](puppet-enterprise/micro-architecture/code-manager.md) 74 | - [File sync](puppet-enterprise/micro-architecture/file-sync.md) 75 | - Tuning and scaling, typical load patterns 76 | - Proxies and their effect on PE communications 77 | - Log location and how to configure more detailed logging 78 | - Common debugging tools and methods 79 | - Metrics ingestion from support script using Support’s tooling 80 | - Postgres debugging using pgbadger 81 | - Garbage collection analysis using gceasy.io 82 | 83 | ## APIs 84 | 85 | - [Which API endpoints are available and what they do](apis/) 86 | - [How APIs are used in the normal operation of Puppet](apis/how.md) 87 | - [Puppet DB queries & PQL](apis/puppet-db-queries-pql.md) 88 | 89 | # Puppet Application Manager 90 | 91 | - Containers 92 | - [Kubernetes](pam/kubernetes.md) 93 | - [Installing CD4PE](pam/install-cd4pe.md) 94 | - [Installing Comply](pam/install-comply.md) 95 | 96 | # Coding Best Practices 97 | 98 | - [Style and naming conventions](coding-best-practice/style-and-naming-conventions.md) 99 | - [The roles and profiles pattern](coding-best-practice/roles-and-profiles.md) 100 | - Component modules and how they are different from profiles 101 | - Composition of profiles to reduce duplication (i.e. profile::base vs profile::base::windows) 102 | - [Data separation using hiera](coding-best-practice/data-separation-using-hiera.md) 103 | - [Hiera hierarchy design](coding-best-practice/hiera-hierarchy-design.md) 104 | - [Handling of sensitive data](coding-best-practice/handling-sensitive-data.md) 105 | - PDK 106 | 107 | # Workflow 108 | 109 | - [Git workflows using r10k](workflow/git-workflow-r10k.md) 110 | - [Development Practices for Ops](workflow/dev-practices-for-ops.md) 111 | - [Workflows using CD4PE](workflow/workflows-using-cd4pe.md) 112 | - [CD4PE Custom deployment policies to implement advanced deployments](workflow/custom-deployment-policies.md) 113 | 114 | # OS Skills 115 | 116 | ## Windows 117 | 118 | - General system administration 119 | - Deploying Chocolatey 120 | - Chocolatey Custom Packaging 121 | - DSC 122 | - Active Directory 123 | - WMI Providers 124 | - Privilege escalation 125 | - Powershell scripting 126 | 127 | ## UNIX 128 | 129 | - General system administration 130 | - Service management frameworks (e.g. systemd) 131 | - Moving files between machines 132 | - Configuring package managers 133 | - Creating custom packages 134 | - Users and permissions 135 | - Scripting (Bash, Perl etc.) 136 | -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # A Puppet Learning Path 2 | 3 | Learning Puppet means learning DevOps. To mean, that means Ops and Dev. 4 | Knowing Git, Programming and your OS, in addition to Linux, the ubiquititious Cloud OS is the baseline. 5 | Much of our tooling, both Configuration Management, and (Workload) Orchestration are based around Promise theory. 6 | 7 | So the field is ever expanding. 8 | This is a snapshot. 9 | 10 | This isn't clear, linear path. It can be meandering and looping. Here are some road-posts: 11 | 12 | ## Git 13 | 14 | - ACloud Guru: [Source Control with Git](https://learn.acloud.guru/course/104ff5d6-39c0-4116-b597-4d1bce0b8081/overview) 15 | 16 | ## Unix 17 | 18 | - ACloud Guru: [Linux Professional Institute: System Administrator 101](https://learn.acloud.guru/course/8759d783-6e59-4000-8005-29397540f6c6/overview) 19 | - Applied: [Building Linux from Scratch](https://linuxfromscratch.org/lfs/read.html) 20 | - Beyond Linux: [The FreeBSD Handbook](https://docs.freebsd.org/en/books/handbook/) 21 | 22 | ## Windows 23 | 24 | TODO find something — anything! — on windows 😰 25 | 26 | ## DevOps 27 | 28 | - Book: [Phoenix Project](https://itrevolution.com/the-phoenix-project/) 29 | - Book: [The Unicorn Project](https://itrevolution.com/the-unicorn-project/) 30 | - Book: [DevOps Handbook](https://itrevolution.com/the-devops-handbook/) 31 | - ACloud Guru: [DevOps Essentials](https://learn.acloud.guru/course/a9b44e15-6b47-4fc7-b6f1-62af794bb825/overview) 32 | - ACloud Guru Advanced: [Hands-on GitOps](https://learn.acloud.guru/course/7174b900-cf14-45e9-8f42-52f153e00857/overview) 33 | 34 | ## Programming Ruby 35 | 36 | - Book: [Ruby Wizardry for Kids](https://nostarch.com/rubywizardry) 37 | - Codeacademy: [Learn Ruby](https://www.codecademy.com/learn/learn-ruby) 38 | 39 | ## Declarative 40 | 41 | - Mina: [Declarative Programming with Puppet and Make](https://github.com/puppetlabs/learn-to-be-a-puppet-engineer/tree/main/declarative) 42 | - Book: [Declarative Programming with Puppet](https://www.oreilly.com/library/view/learning-puppet-4/9781491907993/ch01.html) 43 | 44 | ## Puppet 45 | 46 | - Learn Puppet: [Puppet Practice Labs](https://learn.puppet.com/practicelabcatalog) 47 | - Learn Puppet: [Puppet Practitioner](https://learn.puppet.com/instructor-led-training/puppet-practitioner) 48 | - Learn Puppet: [Puppet Learning VM](https://puppet.com/try-puppet/puppet-learning-vm/) 49 | - Modeling Infrastructures with Puppet: [Designing system configs: roles & profiles]](https://puppet.com/docs/pe/latest/osp/designing_system_configs_roles_and_profiles.html) 50 | 51 | ## Puppet Enterprise 52 | 53 | - [Puppet Enterprise Guide](https://puppet-enterprise-guide.com/) 54 | - Puppet Training: Installing PE 55 | - Homework: Install PE! 56 | 57 | ## Bolt 58 | 59 | - Learn Puppet: [Introduction to Bolt](https://learn.puppet.com/course/puppet-orchestration-bolt-and-tasks) 60 | - Learn Puppet: [Puppet Learning VM](https://puppet.com/try-puppet/puppet-learning-vm/) 61 | - When to use Bolt 62 | 63 | 64 | ## Debugging 65 | 66 | - Book: [Why Programs Fail](https://www.sciencedirect.com/book/9781558608665/why-programs-fail) 67 | 68 | ## Cloud 69 | 70 | Learn one of these in-depth, learn the others when needed. 71 | 72 | - ACloud Guru: [GCP DevOps](https://learn.acloud.guru/learning-path/gcp-devops) and [GCP Architecture](https://learn.acloud.guru/learning-path/gcp-architecture) 73 | - ACloud Guru: [Azure DevOps](https://learn.acloud.guru/learning-path/azure-devops) and [Azure Architecture](https://learn.acloud.guru/learning-path/azure-architecture) 74 | - ACloud Guru: [AWS DevOps](https://learn.acloud.guru/learning-path/aws-devops) and [AWS Architect](https://learn.acloud.guru/learning-path/aws-architect) 75 | - OpenStack 76 | - VMWare 77 | 78 | ## Kubernetes 79 | 80 | - ACloud Guru: [Kubernetes Essentials](https://learn.acloud.guru/course/2e0bad96-a602-4c91-9da2-e757d32abb8f/overview) 81 | - ACloud Guru: [Kubernetes Deep Dive](https://learn.acloud.guru/course/kubernetes-deep-dive/overview) 82 | - ACloud Guru: [Monitoring Kubernetes with Prometheus](https://learn.acloud.guru/learning-path/cloud-adjacent-devops#:~:text=Monitoring%20Kubernetes%20With,5%3A00%3A00) 83 | - ACloud Guru: [Kubernetes the Hard Way](https://learn.acloud.guru/course/8832e727-9101-4785-8ea6-e8057ad62f69/overview) 84 | 85 | 86 | ## CD4PE 87 | 88 | - Learn Puppet: [ Streamline Your Code Deployment Pipeline With CD4PE](https://learn.puppet.com/course/streamline-your-code-deployment-pipeline-with-cd4pe) 89 | - Homework: Workflows 90 | - TODO: create Homework: Install CD4PE 91 | 92 | ## Promises 93 | 94 | - Theory (free) Book: [Promises](http://markburgess.org/promises.html) 95 | -------------------------------------------------------------------------------- /apis/DataFlowNodes_updated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/learn-to-be-a-puppet-engineer/65d6dd5c2cc1215da8733ea62c76e03999fe10a7/apis/DataFlowNodes_updated.png -------------------------------------------------------------------------------- /apis/README.md: -------------------------------------------------------------------------------- 1 | # APIs 2 | 3 | ## Documentation 4 | 5 | [APIs Index](https://puppet.com/docs/pe/latest/api_index.html) 6 | 7 | ## Education 8 | 9 | Definitely not covered. 10 | 11 | ## Other 12 | 13 | Do we teach it in any other way, homework, blog posts, for example? 14 | -------------------------------------------------------------------------------- /apis/how.md: -------------------------------------------------------------------------------- 1 | # How APIs are used in the normal operation of Puppet 2 | 3 | ![a graph between two nodes: Puppet Server and Puppet Agent](DataFlowNodes_updated.png) 4 | 5 | ## Documentation 6 | 7 | 8 | 9 | ## Education 10 | 11 | This isn't taught in GSWP which sucks. 12 | 13 | It is taught properly in Practitioner. 14 | 15 | ## Other 16 | 17 | We don't have any real homework for this, but the fact that PSEs need to be able to teach Practitioner means that they will naturally have to learn it 18 | -------------------------------------------------------------------------------- /apis/puppet-db-queries-pql.md: -------------------------------------------------------------------------------- 1 | # Puppet DB queries & PQL 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Is this covered in any of our official education material? 10 | 11 | ## Other 12 | 13 | No homework for this. Would be good to write some though, just giving people some tasks like "Go get this from the database" and then they have to work out how to write the PQL query 14 | -------------------------------------------------------------------------------- /coding-best-practice/data-separation-using-hiera.md: -------------------------------------------------------------------------------- 1 | # Data Separation Using Hiera 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | 8 | ## Education 9 | 10 | Covered in detail in GSWP, and Practitioner. 11 | 12 | ## Other 13 | 14 | The basics three homework requires hiera when we come to expending the requirements with the "scope creep" section 15 | -------------------------------------------------------------------------------- /coding-best-practice/handling-sensitive-data.md: -------------------------------------------------------------------------------- 1 | # Handling Sensitive Data 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | Old: 8 | 9 | ## Education 10 | 11 | Covered in both GSWP, and Practitioner. 12 | 13 | ## Other 14 | 15 | - [Encryption in Puppet using hiera-eyaml - Simon Hildrew](https://www.youtube.com/watch?v=8VWT8E84VG8&ab_channel=sihil) 16 | - [Introduction To Puppet | Encrypting Data In Hiera | Part 3 | Eduonix](https://www.youtube.com/watch?v=4sqvvg-m2Cw&ab_channel=EduonixLearningSolutions) 17 | 18 | It's also covered in the "scope creep" section if the basics three homework under "You might want to also add the requirement that each team doesn't want the other team to know their password. How could we deal with that?" in the hidden section that is only for reviewers: 19 | -------------------------------------------------------------------------------- /coding-best-practice/hiera-hierarchy-design.md: -------------------------------------------------------------------------------- 1 | # Hiera hierarchy design 2 | 3 | ## Documentation 4 | 5 | I don't think there is any opinionated docs on hiera hierarchy design 6 | 7 | ## Education 8 | 9 | Nope. 10 | 11 | ## Other 12 | 13 | We have a few small things about hiera here: 14 | 15 | * 16 | * 17 | * 18 | 19 | Possibly the book [Puppet Best Practices](https://www.oreilly.com/library/view/puppet-best-practices/9781491922996/ch06.html) would be a good resource. 20 | 21 | Also as part of the code review for basics three will involve looking at the hierarchy that someone has created and making sure that it makes sense. 22 | Though to be fair there are certainly a few things that we could be missing here. e.g. how many layers should you have, what sorts of facts should be part of a hierarchy, what you should and shouldn't do regarding nesting of files, etc. 23 | -------------------------------------------------------------------------------- /coding-best-practice/roles-and-profiles.md: -------------------------------------------------------------------------------- 1 | # Roles and Profiles Pattern 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | - 8 | 9 | 10 | ## Education 11 | 12 | Covered in detail, in both GSWP, and Practitioner. 13 | 14 | ## Other 15 | 16 | - 17 | - 18 | - [Puppet book](https://www.oreilly.com/library/view/puppet-best-practices/9781491922996/ch07.html) 19 | - [rnelson0](https://rnelson0.com/2017/03/08/what-goes-in-a-puppet-role-or-profile/) 20 | - [Puppet Best Practices: Roles & Profiles – Gary Larizza at PuppetConf 2016](https://www.youtube.com/watch?v=RYMNmfM6UHw&ab_channel=Puppet) 21 | 22 | Also Gary's blog: 23 | 24 | * 25 | * 26 | * 27 | * 28 | 29 | Also covered in the ["basics three" homework](https://confluence.puppetlabs.com/display/PS/PS+Onboarding+and+Continuation+Training) 30 | 31 | -------------------------------------------------------------------------------- /coding-best-practice/style-and-naming-conventions.md: -------------------------------------------------------------------------------- 1 | # Style and Naming Conventions 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | This is kind of covered generally in the courses but I don't think there is anything specifically dedicated to it 10 | 11 | ## Other 12 | 13 | The homework in "basics three" and "intermediate four" all include code review elements so will cover this quite well 14 | -------------------------------------------------------------------------------- /declarative/README.md: -------------------------------------------------------------------------------- 1 | # Declarative Coding Concepts 2 | 3 | Puppet is in the class of Domain Specific Languages that follow a declarative programming model. Declarative programming is often defined as any style of programming that isn't imperative, but that's not a very useful definition. 4 | 5 | ## DSL 6 | 7 | Before looking at examples to aid our understanding, we should clarify what "Domain-specific language" means. 8 | 9 | Again, this is often contrasted with General Purpose Languages, but the main difference is that DSLs are often not Turing-complete. (Though some [accidentally Turing Complete](https://www.gwern.net/Turing-complete)) 10 | 11 | Such restricted languages cannot solve all problems that a Turing Complete language can solve, but that's not the point. The power of Domain Specific Languages lies in easily solving _domain-specific problems_. In Puppet's case, that problem domain is configuring computers and software, and automating installations thereof on hundreds or thousands or more machines. 12 | 13 | ## Features 14 | 15 | Another well-known DSL is Make. Its problem domain is that of building software. 16 | 17 | What both have in common is that they rely heavily on a set of _predefined functionality_, and on the user structuring this functionality with _dependencies_. 18 | 19 | They are also both _idempotent_, that is, they will not touch a _target_ (in Make) or a _resource_ (in Puppet), if it is already found to be in the correct state. 20 | 21 | This idempotence and **_correctness_** is much easier to achieve when each resource/target is only defined once. This _uniqueness_ constraint is a lot stronger in Puppet: Make will only warn you when you redefine a target, Puppet will throw an error. 22 | 23 | From these constraints, Make and Puppet build a DAG (Directed Acyclic Graph - Puppet's Logo!). Make uses it to heavily parallelize a build. 24 | 25 | In Puppet, the DAG is used only to verify correctness, because parallelization might be impossible (API calls), or too error prone (package installation). 26 | 27 | ## Make 28 | 29 | Let's take a look at Make. As mentioned before, Make has a lot of built-in rules. 30 | 31 | To compile a simple C program such as this ``hello.c`` file, 32 | 33 | ```c 34 | # include 35 | 36 | int main() { 37 | printf("Hello, World!\n"); 38 | return 0; 39 | } 40 | ``` 41 | 42 | we call ``make hello``: 43 | 44 | ```sh 45 | meena@computer > make hello 46 | cc hello.c -o hello 47 | meena@computer > 48 | ``` 49 | 50 | Note that different Makes can have different defaults. 51 | 52 | Here's the same run with BSD Make: 53 | 54 | ```sh 55 | meena@computer > bmake hello 56 | cc -pipe -O2 -o hello hello.c 57 | meena@computer > 58 | ``` 59 | 60 | This isn’t a world-shaking difference, and is only something that systems-programmers may need to keep in mind, when porting their software to different systems. 61 | 62 | We can now execute ``./hello`` and get a nice greeting of ``Hello, World!``. Crucially, if we run ``make hello`` again, we get: 63 | 64 | ```sh 65 | meena@computer > make hello 66 | make: `hello' is up to date. 67 | meena@computer > 68 | ``` 69 | 70 | There's one clear advantage to putting these things into a ``Makefile``: we can define our own convenience targets, while re-using the built-in defaults: 71 | 72 | ```makefile 73 | hello: hello.c 74 | $(CC) $(CFLAGS) -o hello hello.c 75 | 76 | .PHONY: clean 77 | clean: 78 | rm -f -- hello 79 | ``` 80 | 81 | Let’s start from the top: ``hello`` is our target, and it _depends_ on ``hello.c``. Previously, Make went looking for a dependency, and you can see this process (without a Makefile) by running ``make -d hello`` . 82 | 83 | To build our ``hello`` _target_, we re-use the built-ins for ``$(CC)`` (the default system C Compiler) and ``$(CFLAGS)`` (flags passed to that C Compiler). These built-ins represent the knowledge inherent in Make, and also, in part, the _imperative_ parts. Using them we can focus on _declaring the intent_: What needs to be done? In roughly what order? This way, the _how_ can be left to magic. 84 | 85 | ``hello`` being the first target in the ``Makefile``, is also the _default_ target, 86 | 87 | so we can now call ``make`` without parameters: 88 | 89 | ```sh 90 | meena@computer > make 91 | cc -o hello hello.c 92 | meena@computer > make 93 | make: `hello' is up to date. 94 | ``` 95 | 96 | We now also declare a new, [`.PHONY`](https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html) target called ``clean``. We often see a `clean` target and there cannot be a default for it, so we have to define our own. Our ``clean`` target is "``.PHONY``", because it produces nothing that Make can track. That means, that the ``clean`` target is _not idempotent_, we can run it as often as we want, and it will always (attempt to) delete our ``hello`` binary: 97 | 98 | ```sh 99 | meena@computer > make clean 100 | rm -f -- hello 101 | meena@computer > make clean 102 | rm -f -- hello 103 | meena@computer > make clean 104 | rm -f -- hello 105 | meena@computer > 106 | ``` 107 | 108 | Make is very good at tracking things that exist, but not so good at tracking their purposeful absence. We can forgive Make this deficiency, after all, it's in the name: it's supposed to _make_ things. 109 | 110 | ### Dependencies 111 | 112 | Let's extend our C program, 113 | 114 | ```c 115 | # include 116 | 117 | int main(int argc, const char **argv) { 118 | if (argc == 2) { 119 | printf("Hello, %s!\n", argv[1]); 120 | } else { 121 | printf("Hello, World!\n"); 122 | } 123 | return 0; 124 | } 125 | ``` 126 | 127 | and its Makefile to show-case dependencies: 128 | 129 | ```makefile 130 | WHO ?= Mina Galić 131 | 132 | greet: hello 133 | ./hello "$(WHO)" 134 | 135 | hello: hello.c 136 | $(CC) $(CFLAGS) -o hello hello.c 137 | 138 | .PHONY: clean 139 | clean: 140 | rm -f -- hello 141 | ``` 142 | 143 | Let's summarize this: 144 | 145 | * Our new _default_ target is now ``greet`` 146 | * it depends on ``hello``, which 147 | * depends on ``hello.c``. 148 | 149 | That means: If ``hello.c`` changes, ``hello`` is recompiled. 150 | 151 | The ``greet`` target then calls ``./hello`` to greet the author. 152 | 153 | In addition, the ``WHO`` variable can be overridden (thanks to the ``?=`` assignment), to greet someone else: 154 | 155 | ```sh 156 | meena@computer > make 157 | cc -o hello hello.c 158 | ./hello "Mina Galić" 159 | Hello, Mina Galić! 160 | meena@computer > make greet WHO="Someone Else" 161 | ./hello "Someone Else" 162 | Hello, Someone Else! 163 | meena@computer > 164 | ``` 165 | 166 | ## Puppet 167 | 168 | At first glance the many built-ins in Puppet make it seem quite magical too. One thing we can do is _query_ the system with Facter, 169 | 170 | ```json 171 | # meena@computer > facter os 172 | { 173 | architecture => "x86_64", 174 | family => "Darwin", 175 | hardware => "x86_64", 176 | macosx => { 177 | build => "20F71", 178 | product => "macOS", 179 | version => { 180 | full => "11.4.0", 181 | major => "11.4", 182 | minor => "0" 183 | } 184 | }, 185 | name => "Darwin", 186 | release => { 187 | full => "20.5.0", 188 | major => "20", 189 | minor => "5" 190 | } 191 | } 192 | ``` 193 | 194 | and the Resource Abstraction Layer: 195 | 196 | ```puppet 197 | # meena@computer > puppet resource user mina.galic 198 | user { 'mina.galic': 199 | ensure => 'present', 200 | comment => 'Mina Galić', 201 | gid => 20, 202 | groups => ['_appserveradm', '_appserverusr', '_lpadmin', 'admin'], 203 | home => '/Users/mina.galic', 204 | password => '*', 205 | shell => '/usr/local/bin/fish', 206 | uid => 501, 207 | } 208 | ``` 209 | 210 | This is very similar to other declarative querying systems like SQL: 211 | 212 | ```sql 213 | select * from user where name='mina.galic'; 214 | > name ensure comment gid uid home shell 215 | > ---------- --------- ---------- ----- ----- ----------------- ------------------- 216 | > mina.galic present Mina Galić 20 501 /Users/mina.galic /usr/local/bin/fish 217 | ``` 218 | 219 | _Types_ like ``user`` encompass parameters for all systems that Puppet can run on, but only display information about the system it actually does run on. 220 | 221 | With this we can create users, files, directories and install packages and manage services on a vast array of Unix systems, as well as Mac OS and Windows. In the Puppet language, we don't tell the computer _how_ to install a package or start a service, we _declare the intent_ of doing that. 222 | 223 | The _Providers_ of those types know _how_ to do that. We only tell it the name and the version: 224 | 225 | ```puppet 226 | # install apache httpd 227 | $package = $facts['os']['family'] ? { 228 | FreeBSD => 'apache24', 229 | Debian => 'apache2', 230 | Windows => 'apache-httpd', 231 | Solaris => 'web/server/apache-24', 232 | default => 'httpd', 233 | } 234 | 235 | $service = $facts['os']['family'] ? { 236 | Windows => 'Apache', 237 | Solaris => '/network/http:apache24', 238 | default => $package, 239 | } 240 | 241 | package { $package: 242 | ensure => installed, 243 | } 244 | 245 | service { $service: 246 | ensure => started, 247 | enabled => true, 248 | subscribe => Package[$package], 249 | } 250 | ``` 251 | 252 | Let's try to break this down into terminology we know: 253 | 254 | * We query the system about itself, 255 | * Based on the OS Family fact, we decide what the package name (``$package``) we need to install will be 256 | * again, based on the OS Family fact, we decide what the service name (``$service``) we need to manage will be 257 | * here we already have a good default: The package name! 258 | * we can now install the package - we're happy with any version, so long as it's ``installed``) 259 | * start the service, and enable it so it'll survive reboots 260 | 261 | ### Dependencies 262 | 263 | The ``subscribe`` line needs its own breakdown, because here is where we handle our _dependencies_: 264 | 265 | * make the ``service`` depend on the ``package`` 266 | * that means: the package will be installed first, then the service will be enabled 267 | * make the ``service`` _subscribe_ to the ``package`` 268 | * that means: when the package changes, the service will be restarted! 269 | 270 | If we ran this Puppet manifest on 17 machines with 17 different OSes, we should end up with Apache HTTPD installed and running on most of them. And a more or less useful error-report from the ones where it failed! 271 | 272 | That was a very long summary of what we did do. Let's briefly summarize what we didn't do: 273 | 274 | * We didn't open a shell, and 275 | * We didn't run ``apt``/``yum``/``dnf``/``brew``/``pkg``/``chocolatey``/etc ``install`` 276 | * We didn't run ``systemctl``/``service``/``launchctl``/``svc``/etc 277 | 278 | Most importantly, we didn't do that on 17 machines! 279 | 280 | ## Uniqueness 281 | 282 | We've mentioned before that Make _encourages_ uniqueness of its targets, while Puppet enforces it. In Puppet, this uniqueness constraint is also extended to variable assignments. 283 | 284 | Let's look at why this might be useful. 285 | 286 | If we have two variable assignments in our Makefile: 287 | 288 | ```makefile 289 | WHO ?= Mina Galić 290 | WHO = Who Could This Be 291 | 292 | greet: hello 293 | ./hello "$(WHO)" 294 | 295 | hello: hello.c 296 | $(CC) $(CFLAGS) -o hello hello.c 297 | 298 | .PHONY: clean 299 | clean: 300 | rm -f -- hello 301 | ``` 302 | 303 | It's impossible to tell what's going to happen, and different things may happen in different contexts: 304 | 305 | ```sh 306 | meena@computer > make greet 307 | Hello, Who Could This Be! 308 | meena@computer > make greet WHO="Magic Lovers" 309 | Hello, Magic Lovers! 310 | meena@computer > 311 | ``` 312 | 313 | This guess-work is taken away in Puppet, by making reassignment impossible: 314 | 315 | ```puppet 316 | $var = 'blah' 317 | $var = 'blubb' 318 | ``` 319 | 320 | results in: 321 | 322 | ``` 323 | Error: Evaluation Error: Cannot reassign variable '$var' (file: var.pp, line: 2, column: 6) on node computer 324 | ``` 325 | 326 | That means that variables in Puppet are like variables in Mathematics, or Erlang: Names for an expression. 327 | 328 | This constraint means that we can't reuse a single vessel, for all our trailing thoughts just because it seems familiar. We have to come with new names, often for similar concepts. 329 | 330 | # Converting Shell Scripts into Declarative Code 331 | 332 | The Internet's favorite "Ops" anti-pattern is ``curl | sudo bash``, because it easily relegates **root** control to a script that hardly anyone reviews, and even if they did, there's a way for a server to tell if they are being [piped or downloaded](https://www.idontplaydarts.com/2016/04/detecting-curl-pipe-bash-server-side/). 333 | 334 | A good way to see if we understand what Declarative Coding Concepts are, would be to take such a popular script and see if we can convert it. 335 | 336 | So let's take a look at [Nodesource](https://nodesource.com/)'s [RPM](https://rpm.nodesource.com/setup_16.x) or [Apt](https://deb.nodesource.com/setup_16.x) install script, to setup NodeJS. 337 | 338 | ## Homework 339 | 340 | * Pick one or both scripts 341 | * identify _Checkpoints_ 342 | * identify _Dependencies_ 343 | * identify _Breakpoints_ 344 | * Which parts of the script can discarded? 345 | * Which parts, if any, can be reused? 346 | * Which parts, if any, can be replaced with Facter's knowledge? 347 | * Which parts, if any, can be replaced with Puppet Modules or builtins? 348 | -------------------------------------------------------------------------------- /declarative/examples/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /declarative/examples/Makefile: -------------------------------------------------------------------------------- 1 | WHO ?= Mina Galić 2 | 3 | greet: hello 4 | ./hello "$(WHO)" 5 | 6 | hello: hello.c 7 | $(CC) $(CFLAGS) -o hello hello.c 8 | 9 | .PHONY: clean 10 | clean: 11 | rm -f -- hello 12 | -------------------------------------------------------------------------------- /declarative/examples/declarative.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puppetlabs/learn-to-be-a-puppet-engineer/65d6dd5c2cc1215da8733ea62c76e03999fe10a7/declarative/examples/declarative.sqlite -------------------------------------------------------------------------------- /declarative/examples/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, const char **argv) { 4 | if (argc == 2) { 5 | printf("Hello, %s!\n", argv[1]); 6 | } else { 7 | printf("Hello, World!\n"); 8 | } 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /declarative/examples/var.pp: -------------------------------------------------------------------------------- 1 | $var = 'blah' 2 | $var = 'blubb' 3 | -------------------------------------------------------------------------------- /declarative/idempotence/README.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | Starting [here](https://puppet.com/docs/puppet/latest/puppet_overview.html#key_concepts_puppet-idempotency) the canonical document (according to our Search) explaining this is [Understanding Idempotency](https://puppet.com/docs/pe/2019.2/understanding_idempotency.html) 4 | 5 | Note that it doesn't exist in the Puppet Open Source section or in the newer version of the PE documentation. 6 | Or rather, it was folded into a [different document](https://puppet.com/docs/pe/2021.2/managing_windows_nodes.html#understanding_idempotency) which seems really confusing. 7 | 8 | ## Eductation 9 | 10 | Not covered in GSWP. 11 | 12 | In the Puppet Practitioner, it only looks like it's just a rehash of something people should already be familiar with. 13 | 14 | ## Other 15 | 16 | Contrast and compare: [Idempotence vs Immutability](https://devops.stackexchange.com/questions/2484/a-comparison-of-idempotence-and-immutability) 17 | 18 | Theoretical Deep Dive: 19 | 20 | - 21 | - and 22 | - 23 | -------------------------------------------------------------------------------- /declarative/idempotence/exec-resources.md: -------------------------------------------------------------------------------- 1 | # Idempotent Exec Resources 2 | 3 | ## Documentation 4 | 5 | The [canonical documentation](https://puppet.com/docs/puppet/latest/types/exec.html) explains that: 6 | 7 | > Any command in an `exec` resource **must** be able to run multiple times without causing harm --- that is, it must be *idempotent*. There are three main ways for an exec to be idempotent: 8 | 9 | ## Education 10 | 11 | Not covered in GSWP. 12 | 13 | In Puppet Practitioner, the explanation is probably something that only works when a teacher explains it. 14 | 15 | ## Other 16 | 17 | maybe we could link a few bugs here! 18 | -------------------------------------------------------------------------------- /declarative/type-title-namevar.md: -------------------------------------------------------------------------------- 1 | # The type, title and namevar of a resource 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | As far as I can tell this isn't covered in any of the courses 10 | 11 | ## Other 12 | 13 | This would be something good to covered explicitly in some homework or something. It's not super complex but can be confusing initially 14 | -------------------------------------------------------------------------------- /links-to-html.lua: -------------------------------------------------------------------------------- 1 | -- Pandoc Lua filter that converts links ending in .md to .html 2 | -- This way, we can represent them on Github, and convert them to HTML 3 | function Link(el) 4 | el.target = string.gsub(el.target, "%.md", ".html") 5 | return el 6 | end 7 | -------------------------------------------------------------------------------- /pam/install-cd4pe.md: -------------------------------------------------------------------------------- 1 | # Installing CD4PE 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | 8 | ## Education 9 | 10 | Not covered 11 | 12 | ## Other 13 | 14 | It is somewhat covered in ["Basics Six: Workflow with CD4PE and Testing"](https://confluence.puppetlabs.com/display/PS/PS+Onboarding+and+Continuation+Training#PSOnboardingandContinuationTraining-BasicsSix:WorkflowwithCD4PEandTesting) however this piece of homework is well and truly overdue for a revamp. It also doesn't cover things like: 15 | 16 | * Backup and restore 17 | * HA architecture 18 | * How DR works and how to configure it 19 | -------------------------------------------------------------------------------- /pam/install-comply.md: -------------------------------------------------------------------------------- 1 | # Install Comply 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | 8 | ## Education 9 | 10 | Heston Snodgrass has a training that he has created. Need to find where this is *asked 2021-08-17* 11 | 12 | ## Other 13 | 14 | This is not covered in any other homework 15 | -------------------------------------------------------------------------------- /pam/kubernetes.md: -------------------------------------------------------------------------------- 1 | # Kubernetes 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Nope. 10 | 11 | ## Other 12 | 13 | I would recommend that people do the [Kubernetes Deep Dive](https://acloudguru.com/course/kubernetes-deep-dive) course 14 | -------------------------------------------------------------------------------- /plans/basic-plan-writing.md: -------------------------------------------------------------------------------- 1 | # Basic Plan Writing 2 | 3 | ## Documentation 4 | 5 | There are two ways to write Plans, 6 | 7 | - 8 | - 9 | 10 | ## Education 11 | 12 | GSWP has a nothing about how to write Plans 13 | 14 | Puppet Practitioner covers in very basic strokes. 15 | 16 | ## Notes 17 | 18 | To somebody experienced with Puppet, it may seem odd that YAML Plans are the first on the list, however, this is a deliberate choice: 19 | 20 | > We introduce YAML plans first because we want new users unfamiliar with Puppet to have an easy way to start writing plans without needing to learn the Puppet DSL first. – Tom Beech 21 | 22 | My suggestion for people who are familiar with the Puppet DSL, is that they should look at the Puppet language plans first. 23 | -------------------------------------------------------------------------------- /plans/composition-of-plans.md: -------------------------------------------------------------------------------- 1 | # Composition of plans 2 | 3 | Plans that run plans. 4 | 5 | ## Documentation 6 | 7 | I'm not sure it's actually covered here, 8 | 9 | 10 | ## Education 11 | 12 | Education covers the fact that this can be done but not really how to do it or why 13 | 14 | ## Other 15 | 16 | Not covered anywhere else. We should cover this 17 | -------------------------------------------------------------------------------- /plans/dynamic-target-manipulation.md: -------------------------------------------------------------------------------- 1 | # Dynamic Target Manipulation 2 | 3 | Scatter-gather, reduction (i.e. leaving behind failed nodes but continuing with others) and other imperative orchestration techniques. 4 | 5 | ## Documentation 6 | 7 | - [The `reboot` plan does this](https://github.com/puppetlabs/puppetlabs-reboot/blob/main/plans/init.pp#L42) 8 | - [As does the `pe_patch::group_patching`](https://github.com/puppetlabs/pe_patch/blob/main/plans/group_patching.pp#L80) 9 | 10 | This sort of logic will likely be more important when writing custom deployment policies than regular plans since for a custom deployment policy you might want to do things like, 11 | give a plan a set of 100 nodes to deploy to then do one of the following: 12 | 13 | * Deploy in batches of 10 14 | * Deploy 1, then 5 then 20 then 100 etc. and stop if there is a failure 15 | * Run Puppet up to 5 times until the nodes come back cleanly, then stop. If any nodes still have changes this should trigger a failure as the deployment is non-idempotent 16 | 17 | ## Education 18 | 19 | Not really covered. 20 | 21 | ## Other 22 | 23 | Not covered anywhere that I know of 24 | -------------------------------------------------------------------------------- /plans/error-handling-in-plans.md: -------------------------------------------------------------------------------- 1 | # Error handling in Plans 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | What plans are is covered, and the fact that they are capable of doing things like handling errors. 10 | But there isn't anything that actually teaches people how to do this. 11 | 12 | ## Other 13 | 14 | We don't have any homework that requires writing plans, we definitely should 15 | -------------------------------------------------------------------------------- /plans/returning-data-from-plans.md: -------------------------------------------------------------------------------- 1 | # Returning data from a plan 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Plans are covered, as are the fact that plans can run other plans. 10 | But the mechanisms for passing data are not 11 | 12 | ## Other 13 | 14 | Homework doesn't covered this and it definitely should 15 | -------------------------------------------------------------------------------- /puppet-enterprise/installing-pe.md: -------------------------------------------------------------------------------- 1 | # Installing PE 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | We only have a half-day training on *upgrading* PE. 10 | 11 | ## Other 12 | 13 | "Basics One: Setting up an Environment" an "Basics Two: Bolt, Tasks, and installing Puppet agents" from [the homework](https://confluence.puppetlabs.com/display/PS/PS+Onboarding+and+Continuation+Training) cover this in a fair amount of detail. 14 | -------------------------------------------------------------------------------- /puppet-enterprise/macro-architecture.md: -------------------------------------------------------------------------------- 1 | # Puppet Enterprise: Macro Architecture 2 | 3 | By Macro architecture I mean, what are the servers called, how do they talk to each other, what do they do. This is at a machine level rather than a service-by-service level 4 | 5 | ## Documentation 6 | 7 | - [Supported architectures](https://puppet.com/docs/pe/latest/supported_architectures.html) 8 | - [Puppet Enterprise Reference Architectures](https://puppet.com/resources/whitepaper/puppet-enterprise-reference-architectures/) 9 | - 10 | 11 | ## Education 12 | 13 | None of the education material really covers the architectures in any useful way. 14 | I would always recommend that PSEs set aside some time to draw this up on the whiteboard though. 15 | Start with the simplest architecture, explain how we would add compilers to deal with load and what compilers are for. 16 | The talk about HA and super large architectures if needed 17 | 18 | ## Other 19 | 20 | Homework does require the building of larger infrastructures, including HA 21 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/README.md: -------------------------------------------------------------------------------- 1 | # Puppet Enterprise: Micro Architecture 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | The architecture at this level is definitely not covered in training. 10 | 11 | ## Other 12 | 13 | Homework only covers this in a small amount of detail. In order for PSEs to know exactly how all of these components works they will need to do the following: 14 | 15 | * Read the documentation on the software architecture 16 | * Find the docs for the component and read them 17 | * Find the API docs and understand how things communicate with it, what calls you can make, what data it can return etc. 18 | * Build a server and look at what config files get deployed, what is in them? What can you configure? How do you configure them with Puppet? 19 | * Think about how they could become overloaded and if they did, how you would scale them? 20 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/ace-server.md: -------------------------------------------------------------------------------- 1 | # ACE Server 2 | 3 | ## Documentation 4 | 5 | It would apprear that ACE is essentially completely undocumented which is very annoying. The code can be found here: https://github.com/puppetlabs/ace 6 | 7 | ACE is managed by [this profile](https://github.com/puppetlabs/puppet-enterprise-modules/blob/main/modules/puppet_enterprise/manifests/profile/ace_server.pp) 8 | 9 | Request for docs is here: https://tickets.puppetlabs.com/browse/DOCUMENT-1237 10 | 11 | ## Education 12 | 13 | Definitely not covered. 14 | 15 | ## Other 16 | 17 | TBH I don't even really khttps://puppet-kmo.gitbook.io/pe-deploy-and-discover/-Mi21RNRmfAP7onT0Kyl/now what ACE does properly so I have no clue what we need to know about it 18 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/certificate-authority.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: Certificate authority 2 | 3 | ## Documentation 4 | 5 | - [Intermediate CA](https://puppet.com/docs/puppet/latest/server/intermediate_ca.html) 6 | - [Use an independent intermediate certificate authority](https://puppet.com/docs/pe/latest/use_an_independent_intermediate_ca.html) 7 | - [Change the hostname of a primary server](https://puppet.com/docs/pe/2021.2/change_hostname_primary.html) 8 | 9 | ## Education 10 | 11 | Definitely not covered. 12 | 13 | ## Other 14 | 15 | I'd say that the overall structure is reasonably well covered in the docs. 16 | It might be worth getting people to practice creating custom CAs with this tooling and integrating it with PE: https://github.com/dylanratcliffe/puppet_ca_gen 17 | 18 | It is very, very rare that we are required to integrate with an internal CA, but it is common for PSE to have to talk customers out of it. 19 | **This should maybe be homework...** 20 | That conversation usually goes something like this: 21 | 22 | * So usually we create a CA just for Puppet. It uses these certificates for its own authentication and nothing more 23 | * It doesn't add them into the trust store of the server 24 | * It doesn't affect anything other than Puppet 25 | * If you were to use your own CA, that CA is trusted by the entire org right? 26 | * Well if your CA is issuing certs that are trusted by the entire org, that means that the certs that Puppet uses will end up being trusted by the entire org 27 | * Puppet needs a certificate for every server so you're talking about creating thousands of extra certs, all of which are trusted by your org 28 | * Surely this is substantially less secure since you're massively expanding your surface area. If you leave it the default way you don't need to trust anything new. Puppet will just do its own thing with these certs and you can ignore that they are there 29 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/code-manager.md: -------------------------------------------------------------------------------- 1 | # Code Manager 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | - 8 | - 9 | - 10 | 11 | ## Education 12 | 13 | Definitely not covered. 14 | 15 | ## Other 16 | 17 | Basics One homework covers getting this set up. 18 | If we also had some API homework I think that would be basically everything people need to know. 19 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/console-services.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: Console-services 2 | 3 | ## Documentation 4 | 5 | [Node Classifier API v1](https://puppet.com/docs/pe/latest/node_classifier_service_api.html) 6 | 7 | ## Education 8 | 9 | Definitely not covered. 10 | 11 | ## Other 12 | 13 | Not really covered inn anything I don't think. 14 | The only way you really interact with this is via the API or GUI though so the API docs are most of what you need 15 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/file-sync.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: File Sync 2 | 3 | ## Documentation 4 | 5 | - [Developer Documentation](https://github.com/puppetlabs/pe-file-sync/tree/2019.8.x/documentation) 6 | - [About File Sync](https://puppet.com/docs/pe/2021.2/filesync_about.html) 7 | 8 | ## Education 9 | 10 | Definitely not covered. 11 | 12 | ## Other 13 | 14 | Not covered anywhere else that I know of. 15 | For most purposes it's not required to know too much about it other than how to clear caches. 16 | I would probably expect a principal to look into reading the developer docs though and understand all of the options for how exactly it works 17 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/orchestration-services.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: Orchestration-services 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | 8 | 9 | ## Education 10 | 11 | Definitely not covered. 12 | 13 | ## Other 14 | 15 | I don't think we cover this explicitly 16 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/postgresql.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: PostgreSQL 2 | 3 | ## Documentation 4 | 5 | - [Tuning infrastructure nodes](https://puppet.com/docs/pe/latest/tuning_infrastructure.html#shared_buffers) 6 | - [Backing up and restoring Puppet Enterprise](https://puppet.com/docs/pe/latest/backing_up_and_restoring_pe.html) 7 | 8 | ## Education 9 | 10 | Definitely not covered. 11 | 12 | ## Other 13 | 14 | This isn't covered super well. 15 | But also often it doesn't need much touching to be fair. 16 | Often deep PostgreSQL debugging skills are learned through customer emergencies. 17 | 18 | Explanation of [how to tune PostgreSQL autovacuum](https://github.com/dylanratcliffe/pg_autovacuum_cost) 19 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/puppet-db.md: -------------------------------------------------------------------------------- 1 | # Puppet DB 2 | 3 | ## Documentation 4 | 5 | - [Overview and requirements](https://puppet.com/docs/puppetdb/latest/index.html>) 6 | - [Tutorial](https://puppet.com/docs/puppetdb/latest/api/query/tutorial-pql.html) 7 | - [API overview](https://puppet.com/docs/puppetdb/latest/api/index.html) 8 | - [Configuring PuppetDB](https://puppet.com/docs/pe/2021.2/config_puppetdb.html) 9 | 10 | ## Education 11 | 12 | Definitely not covered. 13 | 14 | ## Other 15 | 16 | PSEs will need to understand: 17 | 18 | * That PuppetDB is just an API layer and is not actually the database itself 19 | * How HA works 20 | * How it's possible to have PuppetDB in compilers as well as the primary and secondary, where does the data go? How does it work 21 | * How does PuppetDB work in the extra-large architecture? Where does all the data go? https://github.com/puppetlabs/puppetlabs-peadm 22 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/puppet-server.md: -------------------------------------------------------------------------------- 1 | # Puppet Server 2 | 3 | ## Documentation 4 | 5 | - [Code Manager API](https://puppet.com/docs/pe/latest/code_manager_api.html#code_manager_api) 6 | - [Tuning guide]( https://puppet.com/docs/puppet/latest/server/tuning_guide.html) 7 | - [Configuring Puppet Server](https://puppet.com/docs/pe/latest/config_puppetserver.html) 8 | - [Puppet Server HTTP API overview](https://puppet.com/docs/puppet/latest/server/http_api_index.html) 9 | - [Certificate](https://puppet.com/docs/puppet/latest/server/http_certificate.html) 10 | - [Services endpoint](https://puppet.com/docs/puppet/latest/server/status-api/v1/services.html) 11 | - [Static file content](https://puppet.com/docs/puppet/latest/server/puppet-api/v3/static_file_content.html) 12 | - [Environment modules](https://puppet.com/docs/puppet/latest/server/puppet-api/v3/environment_modules.html) 13 | - [JRuby pool](https://puppet.com/docs/puppet/latest/server/admin-api/v1/jruby-pool.html) 14 | - [Environment cache](https://puppet.com/docs/puppet/latest/server/admin-api/v1/environment-cache.html) 15 | - [Puppet Server HTTP API overview](https://puppet.com/docs/puppet/latest/server/http_api_index.html) 16 | - [Certificate](https://puppet.com/docs/puppet/latest/server/http_certificate.html) 17 | - [Environment cache](https://puppet.com/docs/puppet/latest/server/admin-api/v1/environment-cache.html) 18 | 19 | ## Education 20 | 21 | Definitely not covered. 22 | 23 | ## Other 24 | 25 | It could be valuable to create some homework around the detailed communication that the Puppetserver does, and what resources it has, how it uses them and what knobs there are for scaling 26 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/pxp.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: PXP 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Definitely not covered. 10 | 11 | ## Other 12 | 13 | There's not a whole lot that you need to know about this. 14 | It's worth reading the readme but it's pretty basic and kind of just works. 15 | I would expect a principal to have a good idea of the insides but otherwise of if necessary 16 | 17 | One thing that everyone should know though is the fact that PXP connects using in **inbound** connection and hold this connection open rather than Puppet connecting out to the PXP agent a la Ansible. 18 | Important for firewall rules 19 | -------------------------------------------------------------------------------- /puppet-enterprise/micro-architecture/rbac.md: -------------------------------------------------------------------------------- 1 | # PE Micro Architecture: RBAC 2 | 3 | ## Documentation 4 | 5 | - [RBAC API v2](https://puppet.com/docs/pe/latest/rbac_api_v2_endpoints.html) 6 | - [RBAC API v1](https://puppet.com/docs/pe/latest/rbac_api_v1.html) 7 | - [Managing Access](https://puppet.com/docs/pe/latest/managing_access.html) 8 | - [Activity Service API](https://puppet.com/docs/pe/latest/activity_api.html) 9 | - [Puppetlabs Traning module for RBAC](https://github.com/puppetlabs/pltraining-rbac) 10 | 11 | ## Education 12 | 13 | We have now a Course on Setting up PE, which also covers RBAC. 14 | 15 | ## Other 16 | 17 | [Puppet Enterprise Guide](https://puppet-enterprise-guide.com/) also covers [RBAC](https://puppet-enterprise-guide.com/theory/using-role-based-access-control.html) 18 | -------------------------------------------------------------------------------- /puppet-ruby/custom-facts.md: -------------------------------------------------------------------------------- 1 | # Custom Facts 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | - 8 | 9 | ## Education 10 | 11 | External facts are covered in GSWP. 12 | 13 | Custom facts in ruby are covered in Practitioner. 14 | 15 | ## Other 16 | 17 | Custom facts are often required in consulting so I'd always expect PSEs to be able to do this. 18 | We don't actually cover it in homework but given that PSEs will need to teach training and it's included in the training they will need to know how to do it, especially the labs 19 | -------------------------------------------------------------------------------- /puppet-ruby/custom-functions.md: -------------------------------------------------------------------------------- 1 | # Custom Functions 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Custom functions are covered at a high level in Practitioner. 10 | 11 | However there is no lab 12 | 13 | ## Other 14 | 15 | No homework on this 16 | -------------------------------------------------------------------------------- /puppet-ruby/custom-hiera-backends.md: -------------------------------------------------------------------------------- 1 | # Custom Hiera backends 2 | 3 | ## Documentation 4 | 5 | [Documentation](https://puppet.com/docs/puppet/latest/hiera_custom_backends.html) here is reasonably good. 6 | 7 | ## Education 8 | 9 | Not covered 10 | 11 | ## Other 12 | 13 | We have no way that we teach this, though since it can be written as a puppet-language or ruby function, it is somewhat covered by those topics and having actually done one before probably isn't a hard requirement as long as you have the underlying skills 14 | -------------------------------------------------------------------------------- /puppet-ruby/custom-report-processors.md: -------------------------------------------------------------------------------- 1 | # Custom report processors 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | - 8 | 9 | ## Education 10 | 11 | Not covered in training 12 | 13 | ## Other 14 | 15 | There are some good videos: 16 | 17 | * [Breakout: ServiceNow Integrations in Detail (EMEA)](https://www.youtube.com/watch?v=nGaHGmNQOp4&ab_channel=Puppet) 18 | * [PuppetConf '12: Managing cloud images with custom report processors](https://www.youtube.com/watch?v=Wxfcl3KbBsQ&ab_channel=Puppet) 19 | 20 | Plus examples in code: 21 | 22 | * 23 | * 24 | * 25 | -------------------------------------------------------------------------------- /puppet-ruby/puppet-faces.md: -------------------------------------------------------------------------------- 1 | # Puppet Faces 2 | 3 | Puppet faces are a way to add third-party functionality to puppet. 4 | We can imagine them like third-party plugins to git, where a tool named `git-foo` is put in the path, and then is accessible as `git foo`. 5 | 6 | This then allows integration into our CLI, help, logging, etc, etc… 7 | 8 | ## Documentation 9 | 10 | Where does the documentation live? 11 | 12 | ## Education 13 | 14 | This is not covered in any of our official education material. 15 | 16 | ## Other 17 | 18 | Do we teach it in any other way, homework, blog posts, for example? 19 | 20 | We seem to have filled a lot of the niches and pushed them into puppet itself. 21 | We've kind of settled on putting things that don't fit fully into puppet in their own *external* tools. 22 | -------------------------------------------------------------------------------- /puppet-ruby/rspec-puppet-testing.md: -------------------------------------------------------------------------------- 1 | # Rspec-puppet and testing 2 | 3 | ## Documentation 4 | 5 | - 6 | - 7 | - 8 | - 9 | 10 | ## Education 11 | 12 | This is covered in a fair amount of detail in Practitioner. 13 | 14 | ## Other 15 | 16 | Lots of excellent talks: 17 | 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | 26 | and blog posts: 27 | 28 | - 29 | - 30 | - 31 | 32 | -------------------------------------------------------------------------------- /puppet-ruby/testing-using-litmus.md: -------------------------------------------------------------------------------- 1 | # Testing using Litmus 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Not covered in any courses 10 | 11 | ## Other 12 | 13 | Blog posts: 14 | 15 | * [Litmus: a new module acceptance testing tool](https://puppet.com/blog/litmus-new-module-acceptance-testing-tool/) 16 | * [Integrate Litmus acceptance tests into CD for PE](https://puppet.com/blog/integrate-litmus-acceptance-tests-into-cd-for-pe/) 17 | 18 | Presentations: 19 | 20 | * [Puppet Developer Tools: Litmus and PDK - TP Honey](https://www.youtube.com/watch?v=FYfR7ZEGHoE&t=2s&ab_channel=Puppet) 21 | -------------------------------------------------------------------------------- /puppet-ruby/types-and-providers.md: -------------------------------------------------------------------------------- 1 | # Puppet Types & Providers 2 | 3 | ## Documentation 4 | 5 | - [Resource API](https://puppet.com/docs/puppet/latest/create_types_and_providers_resource_api.html) 6 | - [Types and Providers](https://puppet.com/docs/puppet/latest/types_and_providers_method.html) 7 | 8 | ## Education 9 | 10 | Practitioner covers the purpose of types and providers and the resource abstraction layer (which is important) but doesn't actually go into how to write a type and provider. 11 | 12 | ## Other 13 | 14 | - [The book](https://www.oreilly.com/library/view/puppet-types-and/9781449339319/) 15 | - [Types and providers article by Thomas Uphill @ Packt Hub](https://hub.packtpub.com/types-and-providers/) 16 | - [Puppet - Type and Provider @ tutorialspoint](https://www.tutorialspoint.com/puppet/puppet_type_provider.htm) 17 | - [Easy Types and Providers With Resource API @ YouTube](https://www.youtube.com/watch?v=5FQCRThdM4M&ab_channel=Puppet) 18 | - [Moving From Exec to Types and Providers – Martin Alfke at PuppetConf 2016](https://www.youtube.com/watch?v=Jr8H0wSUMBY&ab_channel=Puppet) 19 | - [Hacking Types and Providers - Introduction and Hands-On, Felix Frank @ puppetconf2015](https://www.youtube.com/watch?v=oYLyWvp3eoE&ab_channel=Puppet) 20 | - [Custom Types & Providers: Modeling Modern REST Interfaces and Beyond- Tyler Langlois, Elastic @ puppetconf2017](https://www.youtube.com/watch?v=95dm1HLYY4w&ab_channel=Puppet) 21 | - [Writing Agentless Types With the Resource API #PuppetizeLive](https://www.youtube.com/watch?v=xY-WEcBqr6o&ab_channel=Puppet) 22 | - [Writing Custom Types to Manage Web-Based Applications – Tim Cinel @ PuppetConf2016](https://www.youtube.com/watch?v=lob9E9SVW5E&ab_channel=Puppet) 23 | 24 | There is a lot of material here so I'm not sure we need to re-cover this ground except maybe to bring it all into the same place and *maybe* create some homework for it? 25 | 26 | 27 | -------------------------------------------------------------------------------- /puppet.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | ]> 8 | 9 | 29 | 30 | 31 | 32 | 33 | import 34 | false 35 | true 36 | undef 37 | 38 | 39 | 40 | in 41 | and 42 | or 43 | 44 | 45 | 46 | and 47 | or 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | -------------------------------------------------------------------------------- /puppet/conditional-logic.md: -------------------------------------------------------------------------------- 1 | # Conditional logic 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | From what I can tell there is nothing in GSWP that is dedicated to conditional logic at all. 10 | Some of the labs include case statements for example but there aren't any slides to actually explain what these are. 11 | 12 | The "Configuration data without hiera" contains examples of if statements but no actual explanation 13 | 14 | There are a few other examples of conditional logic in Practitioner: 15 | 16 | * Code defensively 17 | * Use data types as matching expressions 18 | 19 | 20 | ## Other 21 | 22 | I don't think we really teach this anywhere else 23 | -------------------------------------------------------------------------------- /puppet/data-types.md: -------------------------------------------------------------------------------- 1 | # Data Types 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Data types are covered at a basic level in GSWP. 10 | And then in substantially more detail in Practitioner. 11 | 12 | ## Other 13 | 14 | Another good resource is the actual [specification itself](https://github.com/puppetlabs/puppet-specifications/blob/master/language/types_values_variables.md). Much more advanced but for advanced users is very interesting: 15 | -------------------------------------------------------------------------------- /puppet/defined-types.md: -------------------------------------------------------------------------------- 1 | # Defined Types 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Not covered in GSWP. 10 | 11 | Covered in Practitioner, including a lab. 12 | 13 | ## Other 14 | 15 | Nothing else that I know of. 16 | People often struggle with this quite a lot and it would be really good to find a good way of teaching this. 17 | I think the most important concept is the fact that classes are used to model things that are inherently singleton and defined types are better for things that there can be more than one of. 18 | But many people struggle to combine these concepts, especially within a single module. 19 | Some good examples are things like tomcat, where you can have many instances and therefore it's a defined type. 20 | Or some kind of database software where you only install the database software once but then you can create many database on top of that so it could be a defined type. 21 | 22 | These are also under-utilised in profiles. 23 | They are a very good way of creating interfaces that allow a stable API for hiera data. 24 | For example if you were to create a `mycompany::localuser` type and pull some relevant company-specific data from hiera, 25 | if you then later wanted to change say the default `homedir` or something, 26 | you could edit the defined type without having to change all of the hiera data. 27 | -------------------------------------------------------------------------------- /puppet/lambdas.md: -------------------------------------------------------------------------------- 1 | # Advanced Function Usage (Lambdas) 2 | 3 | ## Documentation 4 | 5 | [Lambdas](https://puppet.com/docs/puppet/latest/lang_lambdas.html). 6 | 7 | Probably good to know: [Function Calls](https://puppet.com/docs/puppet/latest/lang_functions.html) 8 | 9 | Reference of all [Puppet core functions](https://puppet.com/docs/puppet/latest/function.html) plus linkout to the above and other useful things 10 | 11 | ## Trainings 12 | 13 | This isn't covered in GSWP. 14 | 15 | This is covered in a reasonable amount of detail in Practitioner though. 16 | 17 | ## Other 18 | -------------------------------------------------------------------------------- /puppet/puppet-language-functions.md: -------------------------------------------------------------------------------- 1 | # Puppet Language functions 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Puppet-language functions aren't covered at all in GSWP. 10 | 11 | Functions are covered in general in Practitioner and puppet-language functions are mentioned, however only very briefly and there is no lab for them. 12 | 13 | ## Other 14 | 15 | I think that we are probably missing something here. 16 | Often just the fact that it's taught in training means that the PSE will naturally learn it themselves because they don't want to be teaching something that they don't understand. 17 | However this one is covered over so quickly that I think there's a good chance they would miss it 18 | -------------------------------------------------------------------------------- /puppet/ral.md: -------------------------------------------------------------------------------- 1 | # The types and providers abstraction layer 2 | 3 | The types and providers abstraction layer, also called Resource Abstraction Layer (RAL) is a powerful concept in Puppet that seems woefully underdocumented. 4 | 5 | ## Documentation 6 | 7 | The only bit of documentation we have is on [`puppet-resource`](https://puppet.com/docs/puppet/latest/man/resource.html) 8 | 9 | ## Education 10 | 11 | Not covered in GSWP. 12 | 13 | Covered in practitioner, though not in enough detail to actually teach a PSE how it works. 14 | 15 | ## Other 16 | 17 | We don't have any homework that covers writing types and providers and we absolutely should. 18 | This should probably use the [resource API](https://puppet.com/docs/puppet/latest/about_the_resource_api.html) 19 | 20 | Another option would be the Types and Providers book by Dan Body and Nan Liu 21 | -------------------------------------------------------------------------------- /puppet/relationships-and-ordering.md: -------------------------------------------------------------------------------- 1 | # Relationships and Ordering 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | GSWP covers the basics that most people will need including the metaparams, refresh events, things like that. 10 | 11 | Practitioner covers this in a lot more depth including containment. 12 | 13 | ## Other 14 | 15 | N/A 16 | -------------------------------------------------------------------------------- /puppet/resource-type-syntax.md: -------------------------------------------------------------------------------- 1 | # Resource Type Syntax 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Yes, GSWP. 10 | 11 | ## Other 12 | 13 | I don't think that we really cover this anywhere in internal training but it's pretty basic 14 | -------------------------------------------------------------------------------- /puppet/variables-and-scope.md: -------------------------------------------------------------------------------- 1 | # Variables and Scope 2 | 3 | ## Documentation 4 | 5 | * 6 | * 7 | 8 | ## Education 9 | 10 | Variables and scope are covered in reasonable depth in GSWP. 11 | 12 | ## Other 13 | 14 | We also have the scoping homework which is a substantially more advanced dive into scoping as it related to variables and also resources etc. It is under ["Basics Four: Scope"](https://confluence.puppetlabs.com/display/PS/PS+Onboarding+and+Continuation+Training) 15 | -------------------------------------------------------------------------------- /ruby/README.md: -------------------------------------------------------------------------------- 1 | # Ruby: Language Basics 2 | 3 | Would be good to be able to find a super quick ruby course for regular PSEs just give them some idea of what they are looking at. 4 | Senior PSEs could then do a more advanced course. 5 | 6 | For now, here's a few links and books: 7 | 8 | ## No skills required 9 | 10 | As an easy way to get into Ruby for people who have close to no programming experience, I always recommend X for Kids series of books. 11 | In Ruby's case, I'd recommend [Ruby Wizardry](https://www.nostarch.com/rubywizardry) 12 | 13 | ## Some skills required 14 | 15 | The Ruby Website itself has a section dedicated to exploring Ruby from the viewpoints of somebody who already knows *other* languages: https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/ 16 | 17 | This can be very useful to people who already know a language or two, but not ruby. 18 | 19 | ## Deep Dive 20 | 21 | For extremely advanced use, i used to recommend [Ruby Under a Microscope](http://patshaughnessy.net/ruby-under-a-microscope) 22 | 23 | It has a chapter on "Metaprogramming", and one on "JRuby: Ruby on the JVM" both of which are very relevant to Ruby in Puppet, so i wouldn't dismiss it just based on its age (2013) 24 | -------------------------------------------------------------------------------- /ruby/exploring-ruby-with-pry.md: -------------------------------------------------------------------------------- 1 | --- 2 | breaks: false 3 | title: Exploring Ruby with Pry 4 | tags: skills-map 5 | --- 6 | 7 | # Exploring Ruby with Pry 8 | 9 | ## Using Pry 10 | 11 | Before we can get started with pry, we need to install it, see if it works, and configure it so it works a little better. 12 | 13 | ### Install 14 | 15 | Pry is installed as `gem`. 16 | In order to install it to be used with Puppet and Bolt, we need to install it in their environment: 17 | 18 | ```shell 19 | meena@ubuntix ~> sudo -H /opt/puppetlabs/bolt/bin/gem install pry pry-doc 20 | Fetching pry-0.14.1.gem 21 | Successfully installed pry-0.14.1 22 | Parsing documentation for pry-0.14.1 23 | Installing ri documentation for pry-0.14.1 24 | Done installing documentation for pry after 0 seconds 25 | Fetching pry-doc-1.2.0.gem 26 | Successfully installed pry-doc-1.2.0 27 | Parsing documentation for pry-doc-1.2.0 28 | Installing ri documentation for pry-doc-1.2.0 29 | Done installing documentation for pry-doc after 0 seconds 30 | 2 gems installed 31 | meena@ubuntix ~> 32 | ``` 33 | 34 | and the same for for Puppet, with `/opt/puppetlabs/bolt/bin/gem install pry pry-doc`. 35 | 36 | You may notice that we're installing pry and pry-doc. 37 | [pry-doc](https://github.com/pry/pry-doc) provides us with documentation and source code of the core ruby. 38 | This is immensely useful and powerful. 39 | 40 | If you want to do the same for all your Rubies in a PDK install, you can do something like: 41 | 42 | ```fish 43 | meena@ubuntix ~> for gem in /opt/puppetlabs/pdk/private/ruby/*/bin/gem 44 | sudo -H $gem install pry pry-doc 45 | end 46 | ``` 47 | 48 | ### Starting Pry 49 | 50 | To start pry, you can now: 51 | 52 | ``` 53 | meena@ubuntix ~> /opt/puppetlabs/bolt/bin/pry 54 | [1] pry(main)> 55 | ``` 56 | 57 | If you're planning to do something that only root can do with Puppet in Pry, you should prefix that command with `sudo -H`. 58 | 59 | We can now test some basics: 60 | 61 | ```ruby 62 | [1] pry(main)> module PryingOpen 63 | [1] pry(main)* def self.my_third_eye 64 | [1] pry(main)* "ꙮ Welcome ꙮ Explorer ꙮ" 65 | [1] pry(main)* end 66 | [1] pry(main)* end 67 | => :hello 68 | [2] pry(main)> PryingOpen.my_thid_eye 69 | => "ꙮ Welcome ꙮ Explorer ꙮ" 70 | [3] pry(main)> 71 | ``` 72 | 73 | And thanks to 'pry-doc', we can look up documentation for things we have forgotten! 74 | 75 | ```ruby 76 | [6] pry(main)> ? "".length 77 | Error: Cannot locate this method: length. Invoke the 'gem-install pry-doc' Pry command to get access to Ruby Core documentation. 78 | ``` 79 | 80 | or maybe not… 81 | maybe we actually need to read [pry-doc](https://github.com/pry/pry-doc)'s documentation, and learn that we need to `require 'pry-doc'`, in order to use it: 82 | 83 | ```ruby 84 | [7] pry(main)> require 'pry-doc' 85 | => true 86 | [8] pry(main)> ? "".length 87 | 88 | From: string.c (C Method): 89 | Owner: String 90 | Visibility: public 91 | Signature: length() 92 | Number of lines: 7 93 | 94 | Returns the character length of str. 95 | 96 | VALUE 97 | rb_str_length(VALUE str) 98 | { 99 | return LONG2NUM(str_strlen(str, NULL)); 100 | } 101 | [9] pry(main)> 102 | ``` 103 | 104 | That's much better! 105 | 106 | ### Configuring Pry 107 | 108 | Often we'll forget about that step, and get really annoyed at pry or ourselves, so to make our lives a lot easier, we can create a [pryrc](https://github.com/pry/pry/wiki/Customization-and-configuration), which auto-loads pry-doc: 109 | 110 | ```shell 111 | root@ubuntix:~# mkdir -p .config/pry 112 | root@ubuntix:~# echo "require 'pry-doc'" > .config/pry/pryrc 113 | root@ubuntix:~# 114 | ``` 115 | 116 | If we're juggling a lot of different pry sessions, we might also wanna set: 117 | 118 | ```ruby 119 | pry_instance.config.prompt_name = 'my_project_name' 120 | ``` 121 | 122 | within each session, to easier distinguish them. 123 | 124 | It's also good to set your favorite editor, for example: 125 | 126 | ```ruby 127 | Pry.config.editor = 'nvim' 128 | ``` 129 | 130 | And with that, we're ready to revisit some ruby basic and essentials: 131 | 132 | ## Ruby Basics and Essentials 133 | 134 | To people who don't know Ruby, and might even be somewhat new to programming in general, I highly recommend having a book for *children* as a guide. 135 | 136 | [Ruby Wizardry](https://nostarch.com/rubywizardry) is such a book, and it's absolutely beautiful. 137 | 138 | I highly recommend walking thru the book, using `pry` instead of `irb`. 139 | 140 | ### Learning how to explore 141 | 142 | While walking thru a book like Ruby Wizardry in pry, the easiest way we can learn more about Ruby is to issue `?` on everything new in the book, whether we believe that we know it or not does not matter. 143 | 144 | For example: 145 | 146 | ```ruby 147 | [9] pry(main)> ? puts 148 | 149 | From: io.c (C Method): 150 | Owner: Kernel 151 | Visibility: private 152 | Signature: puts(*arg1) 153 | Number of lines: 12 154 | 155 | Equivalent to 156 | 157 | $stdout.puts(obj, ...) 158 | 159 | static VALUE 160 | rb_f_puts(int argc, VALUE *argv, VALUE recv) 161 | { 162 | if (recv == rb_stdout) { 163 | return rb_io_puts(argc, argv, recv); 164 | } 165 | return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv); 166 | } 167 | [10] pry(main)> 168 | ``` 169 | 170 | if the Ruby core source-code feels like to much information for now, you can try to tune it out and only observe it passively. 171 | 172 | However, it is exactly this feature of pry when exploring a complex project that is immensely useful. 173 | 174 | Sometimes this doesn't work very well: 175 | 176 | ```ruby 177 | [10] pry(main)> ? 22 178 | Error: Couldn't locate a definition for 22 179 | [11] pry(main)> 180 | ``` 181 | 182 | in these cases, we can `cd` into the object! 183 | 184 | ```ruby 185 | [11] pry(main)> cd 22 186 | [12] pry(22):1> ls 187 | Comparable#methods: between? clamp 188 | Numeric#methods: 189 | +@ angle clone conjugate eql? i imaginary negative? phase positive? pretty_print_cycle real rect singleton_method_added to_c 190 | abs2 arg conj dup finite? imag infinite? nonzero? polar pretty_print quo real? rectangular step zero? 191 | Integer#methods: 192 | % + < == >> abs ceil digits even? gcdlcm magnitude numerator pred size to_i truncate 193 | & - << === [] allbits? chr div fdiv inspect modulo odd? rationalize succ to_int upto 194 | * -@ <= > ^ anybits? coerce divmod floor integer? next ord remainder times to_r | 195 | ** / <=> >= __pry__ bit_length denominator downto gcd lcm nobits? pow round to_f to_s ~ 196 | locals: _ __ _dir_ _ex_ _file_ _in_ _out_ pry_instance 197 | [13] pry(22):1> 198 | ``` 199 | 200 | and sometimes, we just can't get the documentation for a specific thing: 201 | 202 | ```ruby 203 | [13] pry(22):1> ? if 204 | Error: Couldn't locate a definition for if 205 | [14] pry(22):1> 206 | ``` 207 | 208 | and then other times we might just hit a real wall: 209 | 210 | ```ruby 211 | [14] pry(22):1> ? else 212 | Traceback (most recent call last): 213 | 19: from /opt/puppetlabs/puppet/bin/pry:23:in `
' 214 | 18: from /opt/puppetlabs/puppet/bin/pry:23:in `load' 215 | 17: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/bin/pry:13:in `' 216 | 16: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/cli.rb:112:in `start' 217 | 15: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/pry_class.rb:188:in `start' 218 | 14: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:15:in `start' 219 | 13: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:38:in `start' 220 | 12: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/input_lock.rb:78:in `with_ownership' 221 | 11: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/input_lock.rb:61:in `__with_ownership' 222 | 10: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:38:in `block in start' 223 | 9: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:67:in `repl' 224 | 8: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:67:in `loop' 225 | 7: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:68:in `block in repl' 226 | 6: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/repl.rb:105:in `read' 227 | 5: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/indent.rb:146:in `indent' 228 | 4: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/indent.rb:146:in `each' 229 | 3: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/indent.rb:160:in `block in indent' 230 | 2: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/indent.rb:160:in `times' 231 | 1: from /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/indent.rb:160:in `block (2 levels) in indent' 232 | /opt/puppetlabs/puppet/lib/ruby/gems/2.7.0/gems/pry-0.14.1/lib/pry/indent.rb:160:in `sub!': can't modify frozen String: "" (FrozenError) 233 | meena@ubuntix ~ [1]> 234 | ``` 235 | 236 | all of this is part of exploring and learning our tools' limits. 237 | 238 | ### Basics 239 | 240 | #### Unicode 241 | 242 | Being initially developed in Japan, Ruby has full-fledged Unicode support: 243 | 244 | ```ruby 245 | [63] pry(main)> ć = :acute_c 246 | => :acute_c 247 | [65] pry(main)> acute_c = :ć 248 | => :ć 249 | ``` 250 | 251 | #### Expressions 252 | 253 | After looking at this many pry sessions, perhaps one thing has become clear now: 254 | **Everything** in Ruby returns *something*. 255 | This is because Ruby is an [Expression](https://en.wikipedia.org/wiki/Expression_(programming)) (even [Statements](https://en.wikipedia.org/wiki/Statement_(programming))). 256 | 257 | #### Conditions and Functions 258 | 259 | Since everything is an expression, conditionals are often (shortened and) used for assignment: 260 | 261 | ```ruby 262 | [66] pry(main)> acute_c = :Ć if acute_c == :ć # toggle once 263 | => :Ć 264 | [68] pry(main)> acute_c = if acute_c == :ć then :Ć else :ć end # toggle always 265 | => :ć 266 | [69] pry(main)> acute_c = if acute_c == :ć then :Ć else :ć end # toggle always 267 | => :Ć 268 | ``` 269 | 270 | Instead of copying the same line over and over again, we could pack that into the smallest form of encapsulation / abstraction Ruby has: A function. 271 | 272 | ```ruby= 273 | acute_c = :Ć 274 | 275 | def toggle_acute_c() 276 | acute_c = if acute_c == :ć 277 | :Ć 278 | else 279 | :ć 280 | end 281 | acute_c 282 | end 283 | ``` 284 | 285 | ```ruby 286 | [131] pry(main)> toggle_acute_c() 287 | => :ć 288 | [132] pry(main)> acute_c 289 | => :Ć 290 | [133] pry(main)> acute_c 291 | => :Ć 292 | [134] pry(main)> toggle_acute_c() 293 | => :ć 294 | [135] pry(main)> acute_c 295 | => :Ć 296 | ``` 297 | 298 | well, that's strange! It's almost as if our global `acute_c` and the `acute_c` in the function `toggle_acute_c` are completely independent! 299 | And they are! 300 | [Global variables](https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/globalvars.html) in Ruby need a `$` prefix, and they are very much [frowned upon](https://docs.rubocop.org/rubocop/cops_style.html#styleglobalvars). 301 | 302 | We'll look into better ways of dealing with Data and Scope later, but for now, let's just quick-fix our code: 303 | 304 | ```ruby 305 | $acute_c = :Ć 306 | 307 | def toggle_acute_c() 308 | $acute_c = if $acute_c == :ć 309 | :Ć 310 | else 311 | :ć 312 | end 313 | $acute_c 314 | end 315 | ``` 316 | 317 | or, completely in pry, using the `edit` command: 318 | 319 | ```ruby 320 | [144] pry(main)> edit toggle_acute_c 321 | [145] pry(main)> toggle_acute_c() 322 | => :ć 323 | [146] pry(main)> toggle_acute_c() 324 | => :Ć 325 | [147] pry(main)> 326 | ``` 327 | 328 | Try and see if you can get rid of that last `$acute_c` at the end, since the entire `if/else` should already return the same thing! 329 | 330 | #### Loops and Blocks 331 | 332 | There are loops ways to loop in Ruby: Loops and iterators. 333 | 334 | There are several built-in loop constructs, such as [`for`, `while`/`until`](http://ruby-doc.com/docs/ProgrammingRuby/html/tut_expressions.html#S6), and [Iterators](https://ruby-doc.com/docs/ProgrammingRuby/html/tut_expressions.html#UJ). 335 | 336 | The key difference is what they return. 337 | For example: `for` returns the object it iterated over: 338 | 339 | ```ruby 340 | [48] pry(main)> for i in 1..3 341 | [48] pry(main)* i 342 | [48] pry(main)* end 343 | => 1..3 344 | ``` 345 | 346 | `while`/`until` return `nil`: 347 | 348 | ```ruby 349 | [46] pry(main)> while false 350 | [46] pry(main)* end 351 | => nil 352 | [47] pry(main)> until true 353 | [47] pry(main)* end 354 | => nil 355 | ``` 356 | 357 | Except, that everything can be made to return something else with `break`: 358 | 359 | ```ruby 360 | [44] pry(main)> while :the_music_plays 361 | [44] pry(main)* break :dance 362 | [44] pry(main)* end 363 | => :dance 364 | [45] pry(main)> for i in 1..4 365 | [45] pry(main)* break 17 366 | [45] pry(main)* end 367 | => 17 368 | ``` 369 | 370 | Higher order functions working on iterators return whatever the function says it returns. 371 | 372 | The `each` family generally either returns `self` or a *new* iterator: 373 | 374 | ```ruby 375 | [69] pry(main)> x = 1..4 376 | => 1..4 377 | [70] pry(main)> x.each {|i| i} 378 | => 1..4 379 | ``` 380 | 381 | The map and collect family generally return an array of each processed item (or, again, a new iterator, if no block was passed): 382 | 383 | ```ruby 384 | [5] pry(main)> x.map {|i| i} 385 | => [1, 2, 3, 4] 386 | [6] pry(main)> x.collect {|i| i} 387 | => [1, 2, 3, 4] 388 | [7] pry(main)> 389 | ``` 390 | 391 | This can be quite tedious, if some or many of the objects are `nil`: 392 | 393 | ```ruby 394 | [8] pry(main)> x.map {|i| i.odd?} 395 | => [true, false, true, false] 396 | [9] pry(main)> x.map {|i| i if i.odd?} 397 | => [1, nil, 3, nil] 398 | [10] pry(main)> x.map {|i| i if i.odd?}.compact 399 | => [1, 3] 400 | ``` 401 | 402 | In these cases, we can use `select`: 403 | 404 | ```ruby 405 | [11] pry(main)> x.select {|i| i.odd?} 406 | => [1, 3] 407 | ``` 408 | 409 | If all an iterator function's block does is take the running argument and call a single function with no parameters on it, there's even a shortcut for that in Ruby: 410 | 411 | ```ruby 412 | [12] pry(main)> x.select(&:odd?) 413 | => [1, 3] 414 | ``` 415 | 416 | That might be a little bit too dense, so you might wanna use it sparingly. 417 | 418 | Alternatively, starting Ruby 2.7, you can use: 419 | 420 | ```ruby 421 | [53] pry(main)> x.select{_1.odd?} 422 | => [1, 3] 423 | [54] pry(main)> 424 | ``` 425 | 426 | And of course, just like with loops, all blocks can be made to return anything with `break`: 427 | 428 | ```ruby 429 | [15] pry(main)> x.reduce {break :no} 430 | => :no 431 | ``` 432 | 433 | ### Modules, Classes and Scope 434 | 435 | The [Ruby Basics](https://bparanj.gitbooks.io/ruby-basics/content/) (Git)Book, has a beautiful chapter [explaining Class, Object and Module Hierarchy](https://bparanj.gitbooks.io/ruby-basics/content/third_chapter.html). 436 | I highly suggest reading this, as in this bit here, we will only focus on Scope. 437 | 438 | But here's a partial summary: 439 | 440 | ```ruby 441 | [168] pry(main)> name 442 | => :Mina_Galić 443 | [169] pry(main)> name.class 444 | => Symbol 445 | [170] pry(main)> Symbol.superclass 446 | => Object 447 | [171] pry(main)> Symbol.superclass.superclass 448 | => BasicObject 449 | [172] pry(main)> Symbol.superclass.superclass.superclass 450 | => nil 451 | ``` 452 | although, `Module` is, perhaps confusingly, a `Class`: 453 | 454 | ```ruby 455 | [180] pry(main)> Module.class 456 | => Class 457 | ``` 458 | 459 | Modules are separate beast: They are mostly used to form Namespaces. 460 | Sometimes they just provide a namespace of useful functions that don't seem to make sense in an object oriented world 461 | 462 | ### Essentials 463 | 464 | By now, you may have noticed that everything in Ruby is an object. 465 | Ruby is a programming language in the tradition of [Smalltalk](http://wiki.c2.com/?SmalltalkLanguage). 466 | In Smalltalk, everything is an object, and objects pass messages to each other. 467 | 468 | Generally, Smalltalk takes this a step further and has no language keywords for conditionals and loops. 469 | They are instead messages (methods) on top of Boolean objects (with Syntactic Sugar). 470 | Whereas Ruby's other *initial* influence was Perl (and Unix). 471 | You can see this in the fact that Ruby has [`BEGIN`/`END` blocks](https://scoutapm.com/blog/ruby-begin-end) and in the fact that everything is file based, not image based, like in Smalltalk. 472 | 473 | A lot of essentials are in the [`Kernel` Module](https://ruby-doc.org/core/Kernel.html): 474 | 475 | ```ruby 476 | [198] pry(main)> ls Kernel 477 | constants: RUBYGEMS_ACTIVATION_MONITOR 478 | Kernel.methods: 479 | Array Pathname __dir__ autoload caller_locations exit! global_variables loop printf rand select srand trace_var 480 | Complex Rational __method__ autoload? catch fail iterator? open proc readline set_trace_func syscall trap 481 | Float String ` binding eval fork lambda p putc readlines sleep system untrace_var 482 | Hash URI abort block_given? exec format load pp puts require spawn test warn 483 | Integer __callee__ at_exit caller exit gets local_variables print raise require_relative sprintf throw 484 | Kernel#methods: 485 | !~ define_singleton_method freeze instance_variable_get method protected_methods send tap untrust 486 | <=> display frozen? instance_variable_set methods public_method singleton_class then untrusted? 487 | === dup hash instance_variables nil? public_methods singleton_method to_enum yield_self 488 | =~ enum_for inspect is_a? object_id public_send singleton_methods to_s 489 | class eql? instance_of? itself pretty_inspect remove_instance_variable taint trust 490 | clone extend instance_variable_defined? kind_of? private_methods respond_to? tainted? untaint 491 | [199] pry(main)> 492 | ``` 493 | 494 | but the two most important ones are [`send`](https://ruby-doc.org/core/Object.html#method-i-send) in [`Object`](https://ruby-doc.org/core/Object.html) and [`method_missing`](https://ruby-doc.org/core/BasicObject.html#method-i-method_missing) in [`BasicObject`](https://ruby-doc.org/core/BasicObject.html) 495 | 496 | Let's look at `send` first: 497 | 498 | ```ruby 499 | [193] pry(main)> 1.2.send(:+, 1.2) 500 | => 2.4 501 | [194] pry(main)> 1.2.send(:+, 2.2) 502 | => 3.4000000000000004 503 | ``` 504 | 505 | Oh computers… wouldn't it be nice, if they knew [how to… compute](https://floating-point-gui.de/)? 506 | 507 | The [`method_missing`] documentation has a beautiful example, unfortunately, the beef of the implementation is… missing. Left as exercise to the student, let's implement it! 508 | By which I mean, search for "roman numerals to int" and copy the [first result](https://iq.opengenus.org/roman-to-integer/). 509 | You'll notice that the example is C++, but after today, that's nothing that'll stop us! 510 | 511 | ```ruby= 512 | def roman_to_int(str) 513 | result = n = 0 514 | str.reverse.each_char.map do |i| 515 | n = case i 516 | when 'i', 'I' 517 | 1 518 | when 'x', 'X' 519 | 10 520 | when 'v', 'V' 521 | 5 522 | when 'l', 'L' 523 | 50 524 | when 'c', 'C' 525 | 100 526 | when 'd', 'D' 527 | 500 528 | when 'm', 'M' 529 | 1000 530 | end 531 | 532 | if (4 * n < result) 533 | result = result - n 534 | else 535 | result = result + n 536 | end 537 | end 538 | result 539 | end 540 | ``` 541 | 542 | or, if you think that we should be using an iterator that already produces the correct result, namely a single integer, rather than returning an array like `map` which we then discard, we could use `reduce`: 543 | 544 | ```ruby 545 | [31] pry(main)> edit roman_to_int 546 | def roman_to_int(str) 547 | n = 0 548 | str.reverse.each_char.reduce(0) do |result, i| 549 | n = case i 550 | when 'i', 'I' 551 | … 552 | end 553 | 554 | if (4 * n < result) 555 | result = result - n 556 | else 557 | result = result + n 558 | end 559 | end 560 | end 561 | ``` 562 | 563 | we can now plug this method into the `Roman` class and test it out for ourselves: 564 | 565 | ```ruby 566 | [14] pry(main)> r.vi 567 | => 6 568 | [15] pry(main)> r.emacs 569 | NoMethodError: undefined method `emacs' for # 570 | from (pry):61:in `rescue in method_missing' 571 | Caused by TypeError: nil can't be coerced into Integer 572 | from (pry):48:in `*' 573 | [16] pry(main)> 574 | ``` 575 | 576 | If you'd also like to give a slightly more meaningful Error message, an `else` to the `case` statement: 577 | 578 | ```ruby 579 | when 'm', 'M' 580 | 1000 581 | else 582 | raise(RangeError, "Invalid Roman numeral '#{i}' in '#{str}'") 583 | end 584 | ``` 585 | 586 | but that still leaves us with a two level stack: 587 | 588 | ```ruby 589 | [44] pry(main)> r.nvim 590 | NoMethodError: undefined method `nvim' for # 591 | from pry-redefined(0x17c#method_missing):7:in `rescue in method_missing' 592 | Caused by RangeError: Invalid Roman numeral 'n' in 'nvim' 593 | from (pry):21:in `block in roman_to_int' 594 | [45] pry(main)> 595 | ``` 596 | 597 | so what we can do instead is reject this earlier, namely in `method_missing`: 598 | 599 | ```ruby 600 | def method_missing(symbol, *args) 601 | str = symbol.id2name 602 | raise(RangeError, "Invalid roman numerals in `#{str}'") unless str.chars.all?(%r{[ivxlcdm]}i) 603 | begin 604 | roman_to_int(str) 605 | rescue 606 | super(symbol, *args) 607 | end 608 | end 609 | ``` 610 | 611 | ```ruby 612 | [49] pry(main)> r.nvim 613 | RangeError: Invalid roman numerals in `nvim' 614 | from pry-redefined(0x17c#method_missing):3:in `method_missing' 615 | [50] pry(main)> 616 | ``` 617 | 618 | ## That's all folks! 619 | 620 | Next time We'll look into Puppet specific Ruby! 621 | -------------------------------------------------------------------------------- /ruby/variables-and-scope.md: -------------------------------------------------------------------------------- 1 | # Ruby: Variables and Scope 2 | 3 | A comprehensive overview of [Variable Scope](https://bparanj.gitbooks.io/ruby-basics/content/part2/scope_of_variables.html) can be found in this [Essential Ruby](https://bparanj.gitbooks.io/ruby-basics/content/) Book. 4 | 5 | There's also a [Redux Version](https://bparanj.gitbooks.io/ruby-basics/content/part2/scope_of_variables_redux.html) of that Chapter. 6 | 7 | Note that this doesn't cover things like [`$globals`](https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/globalvars.html), which are [frowned upon](https://docs.rubocop.org/rubocop/cops_style.html#styleglobalvars). 8 | It also doesn't cover constants. 9 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fffff8; 3 | font-family: sans-serif; 4 | color: #111; 5 | max-width: 34em; 6 | margin: 2.25rem; 7 | font-size: 1.25em; 8 | } 9 | h1, h2, h3, h4, h5, h6 { 10 | font-family: serif; 11 | } 12 | @media (prefers-color-scheme: dark) { 13 | body { 14 | background-color: #151515; 15 | color: #ddd; 16 | } 17 | } 18 | 19 | /* Pre and Code */ 20 | pre { 21 | background-color: #f1f1f1; 22 | display: block; 23 | padding: 1em; 24 | overflow-x: auto; 25 | margin-top: 0px; 26 | margin-bottom: 2.5rem; } 27 | 28 | code { 29 | font-size: 0.9em; 30 | padding: 0 0.5em; 31 | background-color: #f1f1f1; 32 | white-space: pre-wrap; 33 | } 34 | 35 | @media (prefers-color-scheme: dark) { 36 | pre, code { 37 | background-color: #eee; 38 | color: #151515; 39 | } 40 | } 41 | 42 | pre > code { 43 | padding: 0; 44 | background-color: transparent; 45 | white-space: pre; } 46 | 47 | 48 | /* nav */ 49 | 50 | nav { 51 | margin-top: 2.0em; 52 | margin-bottom: 1.5em; 53 | } 54 | 55 | 56 | nav > ul li { 57 | display: inline; 58 | list-style-type: none; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /tasks/passing-parameters-powershell.md: -------------------------------------------------------------------------------- 1 | # Passing Parameters using Powershell 2 | 3 | ## Documentation 4 | 5 | The information on Passing Parameters to Powershell is the same as the information about [Writing Tasks](https://puppet.com/docs/bolt/latest/writing_tasks.html#defining-parameters-in-windows) 6 | 7 | ## Education 8 | 9 | Neither course has any information on how to write your own Tasks. 10 | 11 | ## Other 12 | -------------------------------------------------------------------------------- /tasks/passing-parameters.md: -------------------------------------------------------------------------------- 1 | # Passing Parameters 2 | 3 | ## Documentation 4 | 5 | The information on Passing Parameters is the same as the information about [Writing Tasks](https://puppet.com/docs/bolt/latest/writing_tasks.html#defining-parameters-in-tasks) 6 | 7 | ## Education 8 | 9 | Neither course has any information on how to write your own Tasks. 10 | 11 | ## Other 12 | -------------------------------------------------------------------------------- /tasks/returning-dtata-from-tasks.md: -------------------------------------------------------------------------------- 1 | # Returning Data from Tasks 2 | 3 | ## Documentation 4 | 5 | The information on Returning Data from Tasks is the same as the information about Writing Tasks: https://puppet.com/docs/bolt/latest/writing_tasks.html#returning-structured-output 6 | 7 | ## Education 8 | 9 | Neither course has any information on how to write your own Tasks. 10 | 11 | ## Other 12 | -------------------------------------------------------------------------------- /tasks/secure-code-practices.md: -------------------------------------------------------------------------------- 1 | # Secure Code Practices 2 | 3 | avoiding code injection attacks 4 | 5 | ## Documentation 6 | 7 | 8 | 9 | ## Education 10 | 11 | Writing tasks is covered by we don't currently touch on the possibility of injection-based attacks via task parameters 12 | 13 | ## Other 14 | 15 | Nothing that I know of. 16 | This will be important for people to have in the back of their minds, 17 | but won't be critical to them delivering engagements exactly 18 | -------------------------------------------------------------------------------- /workflow/custom-deployment-policies.md: -------------------------------------------------------------------------------- 1 | # Custom deployment policies 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | Definitely not covered. 10 | 11 | ## Other 12 | 13 | Here is an example if a custom deployment policy that was [created for HSBC](https://github.com/dylanratcliffe/puppet-deployment_signature) 14 | 15 | I wouldn't say the above is a good example since the requirement is pretty dumb in the first place but it is an example of how we can creatively use this to essentially create product features that otherwise don't exist. 16 | 17 | Would be good to get some homework something around this 18 | -------------------------------------------------------------------------------- /workflow/dev-practices-for-ops.md: -------------------------------------------------------------------------------- 1 | # Development Practices for Ops 2 | 3 | This is the "Dev" part if DevOps. PSEs will need to be able to explain the types of development practices that are what make DevOps so powerful. 4 | 5 | ## Documentation 6 | 7 | We don't really cover this too much to be honest 8 | 9 | ## Education 10 | 11 | Not really covered in detail 12 | 13 | ## Other 14 | 15 | - 16 | - 17 | - [This entire series of tutorials on Git](https://www.atlassian.com/git/tutorials/what-is-version-control) 18 | 19 | It's likely that many people that we hire will already understand the benefits that applying development practices to ops will bring. 20 | However especially for CSEs they might not have experience on what the world was like before. 21 | So being able to educate people on "here are all the good ideas that DevOps has taken from software development" is a good idea so that they can articulate this to customers 22 | -------------------------------------------------------------------------------- /workflow/git-workflow-r10k.md: -------------------------------------------------------------------------------- 1 | # Git workflow using r10k 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | This is not really covered. Dylan usually makes sure to cover it on the whiteboard though at the end of the class so that people understand what is possible and what they need to be considering. 10 | 11 | ## Other 12 | 13 | PSEs should have studied [this page](https://confluence.puppetlabs.com/display/PS/Puppet+Workflows) and should be able to present it to GSWP and practitioner classes (or customers) in the form of a whiteboard session explaining what the different workflows could be and what might be the advantages and disadvantages of each. 14 | -------------------------------------------------------------------------------- /workflow/workflows-using-cd4pe.md: -------------------------------------------------------------------------------- 1 | # Workflows using CD4PE 2 | 3 | ## Documentation 4 | 5 | 6 | 7 | ## Education 8 | 9 | This is also not covered in any education material. 10 | 11 | ## Other 12 | 13 | We should have some kind of a standard framework for what we recommend in terms of workflows and pipelines when customers are using CD4PE. 14 | [This confluence page](https://confluence.puppetlabs.com/display/PS/Puppet+Workflows) shows some examples of reasonable workflows from different points on the spectrum when using code manager, however these don't really apply to CD4PE. 15 | 16 | Ideally we would create some content that covers the following: 17 | 18 | * An example of a very lightweight workflow, preferably for a single small team with very little change control overhead and a fast deployment cadence 19 | * An example for a very heavyweight workflow for a single team with a large amount of change control overhead and a slow deployment cadence 20 | * An example of how to deal with many teams. How can their workflows be separated in CD4PE? 21 | 22 | The things that each of these workflows should cover would be: 23 | 24 | * What automated testing should be done and at which point/points in the pipeline? 25 | * Where should impact analysis be placed? 26 | * What happens if there is a problem found in production that requires a quick fix? 27 | --------------------------------------------------------------------------------