summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVikram Karve <vikram.karve@progress.com>2022-01-26 17:15:25 +0530
committerVikram Karve <vikram.karve@progress.com>2022-01-27 10:48:26 +0530
commit75d4fb87007721487cb5f5ce56f768f98f6b514b (patch)
tree6d339974fb1d1cd4fbec929fc8f35c396da77448
parent909e1e1177ca17f6e5ec0dff0920c4bfb9def0da (diff)
downloadchef-75d4fb87007721487cb5f5ce56f768f98f6b514b.tar.gz
Initial draft of knife developer guide
Signed-off-by: Vikram Karve <vikram.karve@progress.com>
-rw-r--r--knife/docs/dev/README.md45
1 files changed, 45 insertions, 0 deletions
diff --git a/knife/docs/dev/README.md b/knife/docs/dev/README.md
new file mode 100644
index 0000000000..76cab6a7be
--- /dev/null
+++ b/knife/docs/dev/README.md
@@ -0,0 +1,45 @@
+# Developer's Guide to Knife
+
+## Overview
+
+knife is a command-line tool that provides an interface between a local Chef repository and the Chef Infra Server. Read more about knife [here](https://docs.chef.io/workstation/knife/).
+
+## Development setup
+
+To setup knife for development-
+1. Fork and clone the [chef repository](https://github.com/chef/chef) in GitHub.
+1. Ensure you have Ruby 3.x installed on your system. You will additionally need tools such as `make` and `gcc`. These are usually already present on most Linux distributions or on your macOS.
+1. Navigate to chef/knife and run `bundle install`.
+1. You can run knife commands in this setup by executing `bundle exec knife <subcommand> <argument> <options>`.
+1. Refer to the article [Setting up Knife](https://docs.chef.io/workstation/knife_setup/) for help with necessary configuration.
+1. byebug or your preferred Ruby debugger can be used to step through the execution flow.
+
+## Execution Flow
+
+The execution starts by instantiating the `Chef::Application::Knife` class with its `run` instance method being invoked. Ref [knife/bin/knife](https://github.com/chef/chef/blob/main/knife/bin/knife). The `Chef::Application` class helps work with CLI command options through the `Mixlib::CLI` module. This `run` instance method in turn invokes the `Chef::Knife`'s `run` class method. `Chef::Knife` acts as the base class for some of the classes associated with knife subcommands such as `Chef::Knife::NodeCreate`, `Chef::Knife::SupermarketList`, `Chef::Knife::Bootstrap`, etc. The role of `Chef::Knife` is summarized here:
+
+- Identify the subcommand supplied.
+- Merge subcommand specific CLI options, if any.
+- Load dependencies to help subclass perform subcommand action.
+- Instantiate the associated subclass.
+- Set up a local-mode Chef server if chef-zero is configured.
+- Run the subcommand action.
+
+With this design, most classes associated with subcommands only need to implement the `run` instance method, while the setup and context is broadly taken care of by `Chef::Knife`. The `Chef::Knife::Bootstrap` class is somewhat of an exception here, as its functionality requires a rather elaborate set of methods and additional classes. That said, not all classes associated with subcommands directly inherit `Chef::Knife`. These inherit the `Chef::ChefFS::Knife` class of the `Chef::ChefFS` module. `Chef::ChefFS::Knife` happens to be a subclass of `Chef::Knife` to avoid redundancy. `Chef::ChefFS` [module](https://www.rubydoc.info/gems/chef/Chef/ChefFS) encapsulates classes and modules that help map the Chef server objects to the local chef repository using a file/directory analogy. It also employs a parallel thread utility to speed up command execution. Examples of such Knife classes are `Chef::Knife::Upload`, `Chef::Knife::Diff` & `Chef::Knife::List`.
+
+## Knife Bootstrap
+
+As `bootstrap` is a remote/distributed operation, there are several phases to it:
+- Set up knife plugin, if needed.
+- Validate if the specified protocol to connect to client node is supported.
+- Validate if the transport and policy options are correct.
+- Establish connection with the server where chef client is to be deployed. The connection is identified by a `Chef::Knife::Bootstrap::TrainConnector` instance.
+- Define the `Chef::Node` instance that represents the server & update this object in Chef server. The class `Chef::Knife::Bootstrap::ClientBuilder` encapsulates this functionality.
+- Update the Chef vault item(s) so the new node has access to those. The class `Chef::Knife::Bootstrap::ChefVaultHandler` encapsulates this functionality.
+- Prepare the `bootstrap.bat` or `bootstrap.sh` script based on the bootstrap template.
+- Copy and execute the bootstrap script on the remote server.
+
+## Knife Plugins
+
+The choice of mapping subcommand action to `Chef::Knife` subclass makes it easy to author knife custom plugins. These can help with extending knife capabilities for specific cloud platforms or customize knife behavior for a subset of subcommands. Follow the instructions [here](https://docs.chef.io/workstation/plugin_knife_custom/) to develop your own knife plugin. Detailed documentation on writing knife cloud plugins is available [here](https://github.com/chef/knife-cloud/blob/main/README.md).
+