diff --git a/ci-automation/0-index.md b/ci-automation/0-index.md new file mode 100644 index 0000000..26e3363 --- /dev/null +++ b/ci-automation/0-index.md @@ -0,0 +1,37 @@ +--- +layout: collection +title: Getting Started with Automating Container Instances Deployment +series: ci-automation +parent: +- tutorials +description: Simplify your deployment of OCI Container Instances by using terraform or the OCI CLI to automate repeatable deployment tasks. +thumbnail: assets/ci-automation.png +author: eli-schilling +tags: +- open-source +- terraform +- iac +- devops +- get-started +sort: asc +date: 2023-02-01 08:13 +xredirect: https://developer.oracle.com/tutorials/ci-automation/ +slug: index +--- + +{% imgx aligncenter assets/ci-automation.png 400 400 "Automating Container Instances" "Container Instances Automation Tutorial Series" %} + +**Difficulty:** Beginner. + +Whether you're new to OCI Container Instances, or you've already kicked the tires a bit, this tutorial will help you round out your expertise with the service and related automation techniques. We will cover Infrastructure as Code (IaC) using Terraform, and the good old fashioned command line interface (for those who prefer scripting). + +Here's what we'll cover: + +1. [Automation Basics - CLI or Terraform](1-automation-basics) +2. [Experiencing Terraform](2-experiencing-terraform) +3. [Understanding the basics of Terraform](3-understanding-terraform-basics) +4. [Terraform variables](4-variables) +5. [Creating Resources with Terraform](5-creating) +6. [Making changes using Terraform](6-changing) +7. [Destroying resources with Terraform](7-destroying) +8. [More Terraform Resources](8-resources) \ No newline at end of file diff --git a/ci-automation/1-automation-basics.md b/ci-automation/1-automation-basics.md new file mode 100644 index 0000000..30991e3 --- /dev/null +++ b/ci-automation/1-automation-basics.md @@ -0,0 +1,82 @@ +--- +title: Automation Basics +parent: +- tutorials +- ci-automation +sidebar: series +tags: +- open-source +- terraform +- iac +- devops +- get-started +categories: +- iac +- opensource +thumbnail: assets/ci-automation.png +date: 2023-02-01 08:13 +description: Heard about Infrastructure as Code (IaC) but not sure what it's about + or why you should care? Tinkered with with OCI CLI but never really peeled back the layers? Well you're in the right place! +toc: true +author: eli-schilling +redirect_from: "/collections/tutorials/1-automation-basics/" +mrm: +xredirect: https://developer.oracle.com/tutorials/ci-automation/1-automation-basics/ +slug: 1-automation-basics +--- +{% imgx aligncenter assets/ci-automation.png 400 400 "Automating Container Instances" "Container Instances Automation Tutorial Series" %} + +What is the importance of automating infrastructure deployment and management? One key tenet of automation is to create consistent, repeatable capabilities that minimize / mitigate the potential for error. Whether you are just experimenting or working towards the implementation of error-free deployment activities, automation can help to realize those goals. + +While there are a myriad of choices when it comes to managing cloud infrastructure, it is best to select a tool that **a)** you're comfortable with, and **b)** can streamline your management tasks while reducing ongoing level of effort. + +In this tutorial we will focus on automating common tasks for OCI Container Instances, while discussing pros and cons of some alternate options. + +For additional information, see: + +* [Signing Up for Oracle Cloud Infrastructure](https://docs.oracle.com/iaas/Content/GSG/Tasks/signingup.htm) +* [About the User Interfaces of the Oracle Integration Oracle Cloud Infrastructure (OCI) Console](https://docs.oracle.com/en/cloud/paas/integration-cloud/integration-cloud-auton/user-interfaces-oracle-integration-cloud-1.html) +* [Working with the Command Line Interface (CLI)](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm) +* [Terraform 101 series](https://developer.oracle.com/tutorials/tf-101) + +## Before you begin + +This tutorial assumes you already have some Terraform and/or OCI CLI experience. While not necessarily required, it would be beneficial that you check out the related tutorials first. Or just dive right in here, and use the other tutorials as a reference. + +* [Terraform 101 series](https://developer.oracle.com/tutorials/tf-101) +* [OCI CLI Playground](https://apexapps.oracle.com/pls/apex/r/dbpm/livelabs/view-workshop?wid=650&clear=RR,180) + +### CLIs + +CLIs are a little bit better than GUIs for helping you manage critical issues. Instead of pointing-and-clicking, commands are directly issued into the application. When you get down to it, CLIs are really just a text user interface. Most CLIs allow for running "headless", meaning they don't require continuous user input (all input can be provided at runtime). One benefit is that it's easier to use CLIs with automated workflows, so it's definitely a step in the right direction. By themselves though, it's impossible to embed any sort of logic when using CLIs, this is where some sort of scripting (shell scripts, Ruby, Python, etc.) can add significant benefit. After determining the set of CLI commands to run, you can utilize the scripting tool of choice to implement logic and create repeatable automation activities. + +### IaC tools + +When you really need to tailor your environment and maximize control over how it performs, IaC tools are what you need. IaC tools are designed from the ground-up to manage infrastructure resources using code. Resources are defined within the code, with the tool itself providing the necessary structure and logic to quickly and easily build a definition of what you need or want an environment to be. The basic "scaffolding" (logic elements, API interactions, etc.) are all abstracted, allowing you to focus on describing the resources you need or want to exist in the environment. + +By far, this is one of the easiest and fastest ways to build and maintain cloud environments. But this isn't just limited to the cloud; on-premesis resources can often be managed with IaC tools as well. Are you using multiple cloud providers? Even more reason to utilize IaC in managing your IT infrastructure. + +With IaC, it's common to use Git on the back-end. Git allows you to get a deep history of changes and its robust version control system enables easy and rapid rollbacks. Additionally, if you use Git for storing the code definitions, you're able to use standard processes and tools to monitor/approve/manage changes before they're made. Whether using policy-as-code (such as [Open Policy Agent](https://www.openpolicyagent.org), with implementations such as [Policy-as-Code on OCI using Open Policy Agent](https://github.com/oracle-devrel/oci-pac-opa)) or a manual pull request (PR)/merge request (MR) review process, you can have a really solid review/approval/compliance mechanism (not to mention yet another audit trail that's separate from the cloud/platform itself). + +#### Infrastructure management + +One of the most common and popular IaC tools is [HashiCorp Terraform](https://www.terraform.io). Other tools, such as [Pulumi](https://www.pulumi.com), are also available, but the common goal of each is the programmatic management of infrastructure. + +#### Configuration management + +Sometimes infrastructure isn't your major concern and what you really need are tools that predominantly operate in the realm of configuration management, such as [Ansible](https://www.ansible.com) or [Chef](https://www.chef.io)/[Cinc](https://cinc.sh). These are all options for managing infrastructure as well, but you may be better off with tools that focus exclusively on *infrastructure management*. For OCI's part, it's certainly no exception in supporting many of these different platforms. + +## CLI and IaC (Terraform) + +For the remainder of this series we are going to explore the capabilities of CLI and IaC for deploying and managing infrastructure. We'll compare the pros and cons of each so you can ultimately make the decision regarding which fits best for your particular situation. + +## What's Next + +By now, you should have a basic understanding of how to configure the tools (Command Line Interface and Terraform) illustrated in this tutorial. You're ready to dive right in and start automating. + +Until your next lesson, happy coding! Take a look at the [next lesson](2-automated-deployment-cli) in the Container Instances Automation 101 series, and go through the process of deploying resources using the OCI CLI. After that, you'll experiment with Terraform before moving on to some more advanced use cases. + +To explore more information about development with Oracle products: + +* [Oracle Developers Portal](https://developer.oracle.com/) +* [Oracle Cloud Infrastructure](https://www.oracle.com/cloud/) \ No newline at end of file diff --git a/ci-automation/2-automated-deployment-cli.md b/ci-automation/2-automated-deployment-cli.md new file mode 100644 index 0000000..fa7aac5 --- /dev/null +++ b/ci-automation/2-automated-deployment-cli.md @@ -0,0 +1,220 @@ +--- +title: Automated deployment with CLI +parent: +- tutorials +- ci-automation +sidebar: series +tags: +- open-source +- iac +- devops +- get-started +categories: +- iac +- opensource +thumbnail: assets/ci-automation.png +date: 2023-02-01 12:00 +description: By this point you should be ready to dive right in and build some automation. Start with the OCI Command Line Interface (CLI) to provision your resources. +toc: true +author: eli-schilling +redirect_from: "/collections/tutorials/1-automation-basics/" +mrm: +xredirect: https://developer.oracle.com/tutorials/ci-automation/1-automation-basics/ +slug: 2-automated-deployment-cli +--- +{% imgx aligncenter assets/ci-automation.png 400 400 "Automating Container Instances" "Container Instances Automation Tutorial Series" %} + +In this tutorial we are going to build a simple virtual network environment and deploy an OCI Container Instance resource. The Container Instance will run two containers; WordPress in one, and MySQL in the other. All of the work is done at the command prompt and when you're finished, you could easily create a bash script for one-click deployment in the future. + +This tutorial is designed for use in the OCI Cloud Shell [OCI Cloud Shell][1]. The Cloud Shell is an easy-to-use terminal built right into the OCI Console, with integrated authorization. If your preference is to install the OCI CLI elsewhere, that is also a cinch, just [Click Here][2] to follow the instructions. When you're ready to go, dive right in! + +### Gather Required Information +The prep work involves identifying your preferred availability domain and working compartment. It is recommended you do not use the *root* compartment in your tenancy, however, the instructions will accommodate use of *root* if you so choose. + +View the list of availability domains in your designated region. We will be collecting both the **name** and **id**. + + oci iam availability-domain list + +![Screenshot of: List of availability domains][2] + +The command output is JSON so there are a few tricks we can use to easily capture the data we need. In another article, we'll delve further into the *--query* functionality of the CLI. For now, you can check out [Jmespath.org][3] if you're curious. + +One more example before we move on. The following will query for the availability domain that includes "AD-1" in the name. If you'd like to use a different AD, just change the number. + + oci iam availability-domain list --query 'data[?contains ("name",`AD-1`)]|[0].[id,name]' --raw-output' + +Capture the availability domain id and name in environment variables. + + adId=($(oci iam availability-domain list --query 'data[?contains ("name",`AD-1`)]|[0].id' --raw-output)) + + adName=($(oci iam availability-domain list --query 'data[?contains ("name",`AD-1`)]|[0].name' --raw-output)) + +You can quickly echo the values to confirm they both loaded properly: +![Screenshot of: echo command output][4] + +The final piece of information required before creating resources is the Compartment OCID. In this example, our compartment name is **Training**. + + compOcid=($(oci iam compartment list --query 'data[?name==`Training`]|[0].id' --raw-output)) + +If you prefer to use the root compartment, the query looks a little different: + + compOcid=($(oci iam compartment list --query 'data[0]."compartment-id"' --raw-output)) + +### Create the network resources +We are going to create a Virtual Cloud Network (VCN) with a single public subnet, a security list that allows ingress traffic on port 80 (to access the WordPress server), an Internet Gateway, and add a route for the Internet Gateway to the default route table. Let's do this! + +Create the VCN! Here we are using 10.0.0.0/16 as the network CIDR. You may opt for a different range...if you do, just make sure you change it accordingly in subsequent steps. +**Note** Because we are loading specific output directly to an environment variable, the command will return nothing to the screen unless there is an error. + + vcnOcid=($(oci network vcn create --cidr-block 10.0.0.0/16 -c $compOcid --display-name ContainerInstance-VCN --dns-label cidemovcn --query 'data.id' --raw-output)) + +Create the security list. When we create the subnet it expects an array of security list IDs, so we'll go ahead and store the array in the variable. + + seclistOcid=('["'$(oci network security-list create --display-name PubSub1 --compartment-id $compOcid --vcn-id $vcnOcid --egress-security-rules '[{"destination": "0.0.0.0/0", "destination-type": "CIDR_BLOCK", "protocol": "all", "isStateless": false}]' --ingress-security-rules '[{"source": "0.0.0.0/0", "source-type": "CIDR_BLOCK", "protocol": 6, "isStateless": false, "tcp-options": {"destination-port-range": {"max": 80, "min": 80}}}]' --query 'data.id' --raw-output)'"]') + +Create the internet gateway, obtain the id of the default VCN route table, and add a new route to the default route to said route table. + + igwId=($(oci network internet-gateway create -c $compOcid --is-enabled true --vcn-id $vcnOcid --display-name CIDemoIGW --query 'data.id' | sed s'/[\[",]//g' | sed -e 's/\]//g')) + + rtId=($(oci network route-table list -c $compOcid --vcn-id $vcnOcid --query 'data[*].id' | sed s'/[\[",]//g' | sed -e 's/\]//g')) + + oci network route-table update --rt-id $rtId --route-rules '[{"cidrBlock":"0.0.0.0/0","networkEntityId":"'$igwId'"}]' + +The final command will output the results of the action: +![Screenshot of: Route table update command][5] + +Now just create the subnet where the Container Instance will be deployed...easy as that! + + pubsubId=($(oci network subnet create --cidr-block 10.0.10.0/24 -c $compOcid --vcn-id $vcnOcid --security-list-ids $seclistOcid --query 'data.id' --raw-output)) + +### Container Instance Resources + +Now that all of the network resources are in place, we're about ready to create the Container Instance resources. Before we just jump right in, however, lets take a look at some of the command parameters. The container instance configuration requires details about the core component, the network, and specifics of each container you intend to run. Deploying WordPress and a database will require two separate containers. + +The **containers** parameter requires a fair amount of JSON. Be careful here because a simple typo could have you running in circles for hours. Later on we'll talk about *json input* for now, let's just see what we're working with. (do not run this code snippet by itself) + + ['{"displayName":"AppContainer","environmentVariables":{"WORDPRESS_DB_HOST":"127.0.0.1","WORDPRESS_DB_NAME":"wordpress","WORDPRESS_DB_PASSWORD":"wordpress","WORDPRESS_DB_USER":"wordpress"},"imageUrl":"docker.io/library/wordpress:latest","resourceConfig":{"memoryLimitInGBs":8,"vcpusLimit":1.5}},{"displayName":"DbContainer","environmentVariables":{"MYSQL_ROOT_PASSWORD":"wordpressonmysql","MYSQL_DATABASE":"wordpress","MYSQL_USER":"wordpress","MYSQL_PASSWORD":"wordpress"},"imageUrl":"docker.io/library/mysql:8.0.31","arguments": ["--default-authentication-plugin=mysql_native_password"],"resourceConfig":{"memoryLimitInGBs":8,"vcpusLimit":1.5}}'] + +Contained within the [] array are two separate container configurations. The first is going to grab the latest WordPress image from DockerHub, allocate resource limitations on the individal container (so it doesn't overrun the other container), and pass environment variables used for app configuration. The second configuration pulls v8.0.31 of the MySQL image, sets environment variables and resource limits again, and passes a runtime argument. Using the argument here will override the MySQL container's **ENTRYPOINT** argument and enables the database password authentication plugin. + +The next parameter to keep in mind is **shape-config** where you define the amount of memory and number of OCPUs allocated to the underlying infrastruture. For optimal performance, ensure the combined total of container resource limitations does not exceed the allocations in shape-config. + + {"memoryInGBs":16,"ocpus":4} + +And finally, the network configuratino, or **vnics** parameter. Notice again the values contained within an array. You may opt to attach multiple VNICs to your container instance. For this go, we'll just use a single VNIC. Provide a display name and subnet ID, and thats it! + + ['{"displayName": "CLI-ContainerInstance-Demo","sunetId":"'$pubsubId'"}'] + +Now put it all together with the *oci container-instances container-instance create* command and...make it so! + + oci container-instances container-instance create --display-name CLI-ContainerInstance-Demo --availability-domain $adName --compartment-id ocid1.compartment.oc1..aaaaaaaav4x6vgcs757ijx7nwyun773mqqlq3p5xmictf2xfnc6k7z25pu3q --containers ['{"displayName":"AppContainer","environmentVariables":{"WORDPRESS_DB_HOST":"127.0.0.1","WORDPRESS_DB_NAME":"wordpress","WORDPRESS_DB_PASSWORD":"wordpress","WORDPRESS_DB_USER":"wordpress"},"imageUrl":"docker.io/library/wordpress:latest","resourceConfig":{"memoryLimitInGBs":8,"vcpusLimit":1.5}},{"displayName":"DbContainer","environmentVariables":{"MYSQL_ROOT_PASSWORD":"wordpressonmysql","MYSQL_DATABASE":"wordpress","MYSQL_USER":"wordpress","MYSQL_PASSWORD":"wordpress"},"imageUrl":"docker.io/library/mysql:8.0.31","arguments": ["--default-authentication-plugin=mysql_native_password"],"resourceConfig":{"memoryLimitInGBs":8,"vcpusLimit":1.5}}'] --shape CI.Standard.E4.Flex --shape-config '{"memoryInGBs":16,"ocpus":4}' --vnics ['{"displayName": "CLI-ContainerInstance-Demo","subnetId":"'$pubsubId'"}'] + +The result of a successful execution will be about a page and a half of JSON output. All the details about the resource just created. +![Screenshot of: JSON command output][6] + +If you look near the end of the output you'll find a section for the *vnics* - and likely you'll find the value of the vnic-id to be null. Don't fret! It takes a few seconds to provision that particular item. And as luck would have it, we can find it easily. + +![Screenshot of: Null vnic id value][7] + +In the JSON output from the command above, locate the **id** for the container instance and copy it (or store it in an environment variable). Then run: + + oci container-instances --container-instance get --container-instance-id + +Now in the output you'll see an **id** for the vnic. +![Screenshot of: Valid vnic id value][8] + +Copy that and use it to run one more command: + + oci network vnic get --vnic-id + +The output of the command will have the details of the VNIC, including the Public IP address. Copy that, navigate to it in a web browser and you should see the WordPress setup page. + +![Screenshot of: Wordpress setup page][9] + +### Leveraging Command Parameter JSON for complex input + +As you can see in the **CREATE** command that was just run, several of the command parameters require complex JSON input. While it is possible to pass directly into the CLI, a preferred approach is to leverage JSON command parameter input. Generating the outline is simple enough and can be done for each of the more complex parameters. It looks like this: + + oci container-instances container-instance create --generate-param-json-input containers >> containers.json + +This will create a JSON file with all of the paramaters available (optional and required) when defining one or more containers for your resource. You can do the same for *shape-config* and *vnics*, resulting in 3 JSON files to pass through the CLI command. The following examples illustrate the minimum configuration required within each file to complete this tutorial. You can, of course, experiment with additional parameter input once you get the hang of this. + +1. **containers.json** + + [ + { + "displayName": "appContainer", + "environmentVariables": { + "WORDPRESS_DB_HOST": "127.0.0.1", + "WORDPRESS_DB_USER": "wordpress", + "WORDPRESS_DB_PASSWORD": "wordpress", + "WORDPRESS_DB_NAME": "wordpress" + }, + "imageUrl": "docker.io/library/wordpress:latest", + "isResourcePrincipalDisabled": true, + "resourceConfig": { + "memoryLimitInGBs": 4.0, + "vcpusLimit": 1.0 + } + }, + { + "arguments": [ + "--default-authentication-plugin=mysql_native_password" + ], + "displayName": "dbContainer", + "environmentVariables": { + "MYSQL_ROOT_PASSWORD": "wordpressonmysql", + "MYSQL_DATABASE": "wordpress", + "MYSQL_USER": "wordpress", + "MYSQL_PASSWORD": "wordpress" + }, + "imageUrl": "docker.io/library/mysql:8.0.31", + "isResourcePrincipalDisabled": true, + "resourceConfig": { + "memoryLimitInGBs": 4.0, + "vcpusLimit": 1.0 + } + } + ] + +2. **vnics.json** + + [ + { + "displayName": "ContainerInstance-Demo", + "freeformTags": { + "Details": "Resource created using CLI" + }, + "isPublicIpAssigned": true, + "skipSourceDestCheck": true, + "subnetId": "ocid1.subnet.oc1.phx." + } + ] + +3. **shape-config.json** + + { + "memoryInGBs": 16.0, + "ocpus": 4.0 + } + +Once you have created and populated the three files, you can simply pass the JSON file as input to your command parameters, resulting in a much cleaner command. + + oci container-instances container-instance create --display-name CLI-ContainerInstance-Demo --availability-domain $adName --compartment-id $compOcid --containers file://containers.json --shape-config file://shape-config.json --vnics file://vnics.json --shape CI.Standard.E4.Flex + +### Conclusion + +There you have it, and well done! You've just completely provisioned OCI Container Instances with related network resources, all from the command line interface! When you're ready to try something a little different, check out the next article on automating Container Instances using Terraform. + + + +[1]: https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cloudshellintro.htm +[2]: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm +[3]: assets/ci-automation-cli-01.png +[4]: https://jmespath.org/ +[5]: assets/ci-automation-cli-02.png +[6]: assets/ci-automation-cli-03.png +[7]: assets/ci-automation-cli-04.png +[8]: assets/ci-automation-cli-05.png +[9]: assets/ci-automation-cli-06.png +[10]: assets/ci-automation-cli-07.png diff --git a/ci-automation/3-automated-deployment-tf.md b/ci-automation/3-automated-deployment-tf.md new file mode 100644 index 0000000..8adeab3 --- /dev/null +++ b/ci-automation/3-automated-deployment-tf.md @@ -0,0 +1,26 @@ +--- +title: Automated Deployment with Terraform +parent: +- tutorials +- ci-automation +sidebar: series +tags: +- open-source +- iac +- terraform +- devops +- get-started +categories: +- iac +- opensource +thumbnail: assets/ci-automation.png +date: 2023-02-01 12:00 +description: Now that you've seen the CLI in action, let's take a look at how to perform similar resource provisioning using Terraform. +toc: true +author: eli-schilling +redirect_from: "/collections/tutorials/1-automation-basics/" +mrm: +xredirect: https://developer.oracle.com/tutorials/ci-automation/1-automation-basics/ +slug: 3-automated-deployment-tf.md +--- +{% imgx aligncenter assets/ci-automation.png 400 400 "Automating Container Instances" "Container Instances Automation Tutorial Series" %} diff --git a/ci-automation/4-incorporate-ocir.md b/ci-automation/4-incorporate-ocir.md new file mode 100644 index 0000000..8adeab3 --- /dev/null +++ b/ci-automation/4-incorporate-ocir.md @@ -0,0 +1,26 @@ +--- +title: Automated Deployment with Terraform +parent: +- tutorials +- ci-automation +sidebar: series +tags: +- open-source +- iac +- terraform +- devops +- get-started +categories: +- iac +- opensource +thumbnail: assets/ci-automation.png +date: 2023-02-01 12:00 +description: Now that you've seen the CLI in action, let's take a look at how to perform similar resource provisioning using Terraform. +toc: true +author: eli-schilling +redirect_from: "/collections/tutorials/1-automation-basics/" +mrm: +xredirect: https://developer.oracle.com/tutorials/ci-automation/1-automation-basics/ +slug: 3-automated-deployment-tf.md +--- +{% imgx aligncenter assets/ci-automation.png 400 400 "Automating Container Instances" "Container Instances Automation Tutorial Series" %} diff --git a/ci-automation/5-container-testing.md b/ci-automation/5-container-testing.md new file mode 100644 index 0000000..1867b1c --- /dev/null +++ b/ci-automation/5-container-testing.md @@ -0,0 +1,38 @@ +--- +title: Automated Deployment and Testing with Container Instances +parent: +- tutorials +- ci-automation +sidebar: series +tags: +- open-source +- iac +- devops +- get-started +categories: +- iac +- opensource +thumbnail: assets/ci-automation.png +date: 2023-02-01 12:00 +description: With the critical components of automated provisioning securely embedded in your brain, its time to put this knowledge into practice. This article will walk through the process of leveraging Container Instances within your CI/CD pipeline for automated testing activities. +toc: true +author: eli-schilling +redirect_from: "/collections/tutorials/1-automation-basics/" +mrm: +xredirect: https://developer.oracle.com/tutorials/ci-automation/1-automation-basics/ +slug: 5-container-testing.md +--- +{% imgx aligncenter assets/ci-automation.png 400 400 "Automating Container Instances" "Container Instances Automation Tutorial Series" %} + + + +Basic idea: +1. Push code to DevOps Repo +2. Trigger Build Pipeline +3. Deliver image to Artifact Repository +4. Create new CI resource +5. Automated validation +6. Destroy CI resource + +Consider writing this from the perspective of moving from manual to automated. +At first we did it all by hand, seemed insurmountable to move to DevOps, taking one bite at a time it was feasible. \ No newline at end of file diff --git a/ci-automation/assets/ci-automation-cli-01.png b/ci-automation/assets/ci-automation-cli-01.png new file mode 100644 index 0000000..cdd8a5d Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-01.png differ diff --git a/ci-automation/assets/ci-automation-cli-02.png b/ci-automation/assets/ci-automation-cli-02.png new file mode 100644 index 0000000..7824123 Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-02.png differ diff --git a/ci-automation/assets/ci-automation-cli-03.png b/ci-automation/assets/ci-automation-cli-03.png new file mode 100644 index 0000000..3d7cfde Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-03.png differ diff --git a/ci-automation/assets/ci-automation-cli-04.png b/ci-automation/assets/ci-automation-cli-04.png new file mode 100644 index 0000000..6540204 Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-04.png differ diff --git a/ci-automation/assets/ci-automation-cli-05.png b/ci-automation/assets/ci-automation-cli-05.png new file mode 100644 index 0000000..afec3c8 Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-05.png differ diff --git a/ci-automation/assets/ci-automation-cli-06.png b/ci-automation/assets/ci-automation-cli-06.png new file mode 100644 index 0000000..5d675e6 Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-06.png differ diff --git a/ci-automation/assets/ci-automation-cli-07.png b/ci-automation/assets/ci-automation-cli-07.png new file mode 100644 index 0000000..f0b3596 Binary files /dev/null and b/ci-automation/assets/ci-automation-cli-07.png differ diff --git a/ci-automation/assets/ci-automation.png b/ci-automation/assets/ci-automation.png new file mode 100644 index 0000000..6693e54 Binary files /dev/null and b/ci-automation/assets/ci-automation.png differ