diff --git a/README.md b/README.md
index 8f05957..bccb1c6 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
:information_source: This repo contains questions and exercises on various technical topics, sometimes related to DevOps and SRE :)
-:bar_chart: There are currently **1600** questions
+:bar_chart: There are currently **1657** questions
:books: To learn more about DevOps and SRE, check the resources in [devops-resources](https://github.com/bregman-arie/devops-resources) repository
@@ -88,6 +88,7 @@
|Name|Topic|Objective & Instructions|Solution|Comments|
|--------|--------|------|----|----|
| Set up a CI pipeline | CI | [Exercise](exercises/devops/ci_for_open_source_project.md) | | |
+| Deploy to Kubernetes | Deployment | [Exercise](exercises/devops/deploy_to_kubernetes.md) | | |
### DevOps Self Assessment
@@ -291,9 +292,13 @@ For more info please read [here](https://www.atlassian.com/continuous-delivery/c
What CI/CD best practices are you familiar with? Or what do you consider as CI/CD best practice?
-* Automated process of building, testing and deploying software
-* Commit and test often
-* Testing/Staging environment should be a clone of production environment
+* Commit and test often.
+* Testing/Staging environment should be a clone of production environment.
+* Clean up your environments (e.g. your CI/CD pipelines may create a lot of resources. They should also take care of cleaning up everything they create)
+* The CI/CD pipelines should provide the same results when executed locally or remotely
+* Treat CI/CD as another application in your organization. Not as a glue code.
+* On demand environments instead of pre-allocated resources for CI/CD purposes
+* Stages/Steps/Tasks of pipelines should be shared between applications or microservices (don't re-invent common tasks like "cloning a project")
@@ -308,6 +313,7 @@ There are multiple approaches as to where to store the CI/CD pipeline definition
1. App Repository - store them in the same repository of the application they are building or testing (perhaps the most popular one)
2. Central Repository - store all organization's/project's CI/CD pipelines in one separate repository (perhaps the best approach when multiple teams test the same set of projects and they end up having many pipelines)
3. CI repo for every app repo - you separate CI related code from app code but you don't put everything in one place (perhaps the worst option due to the maintenance)
+4. The platform where the CI/CD pipelines are being executed (e.g. Kubernetes Cluster in case of Tekton/OpenShift Pipelines).
@@ -329,6 +335,8 @@ to a server will result in a new server instead of updating it. Terraform is an
which follows the immutable infrastructure paradigm.
+#### Software Distribution
+
Explain "Software Distribution"
@@ -338,7 +346,7 @@ From the article: "Thus, software distribution is about the mechanism and the co
-Why are there multiple software distributions? What differences can they have?
+Why are there multiple software distributions? What differences they can have?
Different distributions can focus on different things like: focus on different environments (server vs. mobile vs. desktop), support specific hardware, specialize in different domains (security, multimedia, ...), etc. Basically, different aspects of the software and what it supports, get different priority in each distribution.
@@ -434,12 +442,23 @@ Read about Chaos Engineering [here](https://en.wikipedia.org/wiki/Chaos_engineer
What is "infrastructure as code"? What implementation of IAC are you familiar with?
- IAC (infrastructure as code) is a declerative approach of defining infrastructure or architecture of a system. Some implementations are ARM templates for Azure and Terraform that can work across multiple cloud providers.
+
+IAC (infrastructure as code) is a declerative approach of defining infrastructure or architecture of a system. Some implementations are ARM templates for Azure and Terraform that can work across multiple cloud providers.
+
+
+
+What benefits infrastructure-as-code has?
+
+- fully automated process of provisioning, modifying and deleting your infrastructure
+- version control for your infrastructure which allows you to quickly rollback to previous versions
+- validate infrastructure quality and stability with automated tests and code reviews
+- makes infrastructure tasks less repetitive
How do you manage build artifacts?
- Build artifacts are usually stored in a repository. They can be used in release pipelines for deployment purposes. Usually there is retention period on the build artifacts.
+
+Build artifacts are usually stored in a repository. They can be used in release pipelines for deployment purposes. Usually there is retention period on the build artifacts.
@@ -595,6 +614,7 @@ Read more about it [here](https://sre.google/sre-book/introduction)
|Name|Topic|Objective & Instructions|Solution|Comments|
|--------|--------|------|----|----|
+| Jobs 101 | Jobs | [Exercise](exercises/jenkins/jobs_101.md) | | |
| Remove Jobs | Scripts - Jobs | [Exercise](exercises/jenkins/remove_jobs.md) | [Solution](exercises/jenkins/solutions/remove_jobs_solution.groovy) | |
| Remove Builds | Scripts - Builds | [Exercise](exercises/jenkins/remove_builds.md) | [Solution](exercises/jenkins/solutions/remove_builds_solution.groovy) | |
@@ -710,7 +730,11 @@ You can describe the UI way to add new nodes but better to explain how to do in
What are some of Jenkins limitations?
* Testing cross-dependencies (changes from multiple projects together)
- * Starting builds from any stage (although cloudbees implemented something called checkpoints)
+ * Starting builds from any stage (although Cloudbees implemented something called checkpoints)
+
+
+
+What is the different between a scripted pipeline to declarative pipeline? Which type are you using?
@@ -815,9 +839,23 @@ It's important to note that:
Is there a difference between managed service to SaaS or is it the same thing?
+
+What is auto scaling?
+
+AWS definition: "AWS Auto Scaling monitors your applications and automatically adjusts capacity to maintain steady, predictable performance at the lowest possible cost"
+
+Read more about auto scaling [here](https://aws.amazon.com/autoscaling)
+
+
+
+True or False? Auto Scaling is about adding resources (such as instances) and not about removing resource
+
+False. Auto scaling adjusts capacity and this can mean removing some resources based on usage and performances.
+
+
## AWS
-#### AWS Global Infrastructure
+#### AWS - Global Infrastructure
Explain the following
@@ -1289,20 +1327,6 @@ AWS definition: "Elastic Load Balancing automatically distributes incoming appli
More on ELB [here](https://aws.amazon.com/elasticloadbalancing)
-
-What is auto scaling?
-
-AWS definition: "AWS Auto Scaling monitors your applications and automatically adjusts capacity to maintain steady, predictable performance at the lowest possible cost"
-
-Read more about auto scaling [here](https://aws.amazon.com/autoscaling)
-
-
-
-True or False? Auto Scaling is about adding resources (such as instances) and not about removing resource
-
-False. Auto scaling adjusts capacity and this can mean removing some resources based on usage and performances.
-
-
What types of load balancers are supported in EC2 and what are they used for?
@@ -1561,6 +1585,12 @@ Read more about it [here](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_I
True
+
+What is VPC peering?
+
+[docs.aws](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html): "A VPC peering connection is a networking connection between two VPCs that enables you to route traffic between them using private IPv4 addresses or IPv6 addresses."
+
+
True or False? Multiple Internet Gateways can be attached to one VPC
@@ -2103,7 +2133,6 @@ Learn more about it [here](https://aws.amazon.com/sqs)
## Network
-
What is Ethernet?
@@ -2508,6 +2537,21 @@ Read more [here](https://www.globalsign.com/en/blog/what-is-hsts-and-how-do-i-us
What is the difference if any between SSL and TLS?
+#### Network - Misc
+
+
+What is the Internet? Is it the same as the World Wide Web?
+
+The internet refers to network of networks, transferring huge amounts of data around the globe.
+The World Wide Web is an application running on millions of server, on top of the internet, accessed through what is know as the web browser
+
+
+
+What is the ISP?
+
+ISP (Internet Service Provider) is the local internet company provider.
+
+
## Linux
#### Linux Master Application
@@ -2575,7 +2619,7 @@ For example:
-Some of the commands in the previous question can be run with the -r/-R flag. What does it do? Give an example when to use it
+Some of the commands in the previous question can be run with the -r/-R flag. What does it do? Give an example to when you would use it
The -r (or -R in some commands) flag allows user to run a certain command recursively. For example, listing all the files under the following tree is possible when done recursively (`ls -R`):
@@ -2598,6 +2642,7 @@ It shows a detailed list of files in a long format. From the left:
What are hidden files/directories? How to list them?
+
These are files directly not displayed after performing a standard ls direct listing. An example of these files are .bashrc which are used to execute some scripts. Some also store configuration about services on your host like .KUBECONFIG. The command used to list them is, `ls -a`
@@ -2616,6 +2661,8 @@ They take in input (<) and output for a given file (>) using stdin and stdout.
* cut
* awk
+
+ - sed: a stream editor. Can be used for various purposes like replacing a word in a file: `sed -i s/salad/burger/g`
@@ -2632,6 +2679,12 @@ Using the `mv` command.
* Provides access to the file /tmp/x for everyone
* Change working directory to user home directory
* Replace every occurrence of the word "good" with "great" in the file /tmp/y
+
+ - `rm -rf dir`
+ - `cat or less`
+ - `chmod 777 /tmp/x`
+ - `cd ~`
+ - `sed -i s/good/great/g /tmp/y`
@@ -2648,7 +2701,7 @@ Using the `mv` command.
Explain piping. How do you perform piping?
-Using a pipe in Linux, allows you to send the output of one to another (also called redirection). For example: `cat /etc/services | wc -l`
+Using a pipe in Linux, allows you to send the output of one command to the input of another command. For example: `cat /etc/services | wc -l`
@@ -2667,6 +2720,8 @@ Using a pipe in Linux, allows you to send the output of one to another (also cal
In Linux FHS (Filesystem Hierarchy Standard) what is the /?
+
+The root of the filesystem. The beginning of the tree.
@@ -2677,12 +2732,18 @@ Using a pipe in Linux, allows you to send the output of one to another (also cal
* /home
* /var
* /tmp
+
+ * binaries
+ * configuration files
+ * home directories of the different users
+ * files that tend to change and be modified like logs
+ * temporary files
What is special about the /tmp directory when compared to other directories?
-`/tmp` folder get cleaned automatically, usually upon reboot.
+`/tmp` folder is cleaned automatically, usually upon reboot.
@@ -3045,10 +3106,6 @@ The operating system executes the kernel in protected memory to prevent anyone f
Applications can access system resources and indirectly the kernel space by making what is called "system calls".
-
-What are system calls? What system calls are you familiar with?
-
-
#### Linux Virtualization
@@ -3905,6 +3962,12 @@ dmidecoode
lsblk
+
+True or False? In user space, applications don't have full access to hardware resources
+
+True. Only in kernel space they have full access to hardware resources.
+
+
#### Linux - Random
@@ -3992,7 +4055,25 @@ From Wikipedia: "AWK is domain-specific language designed for text processing an
What is the difference between find and locate?
-#### System Calls
+
+How a user process performs a privileged operation, such as reading from the disk?
+
+Using system calls
+
+
+#### Linux - System Calls
+
+
+What is a system call? What system calls are you familiar with?
+
+
+
+How a program executes a system call?
+
+- A program executes a trap instruction. The instruction jump into the kernel while raising the privileged level to kernel space.
+- Once in kernel space, it can perform any privileged operation
+- Once it's finished, it calls a "return-from-trap" instruction which returns to user space while reducing back the privilege level to user space.
+Explain the fork() system call
@@ -4013,8 +4094,44 @@ fork() is used for creating a new process. It does so by cloning the calling pro
Not enough memory to create a new process
+
+Why do we need the wait() system call?
+
+wait() is used by a parent process to wait for the child process to finish execution.
+If wait is not used by a parent process then a child process might become a zombie process.
+
+
+
+How the kernel notifies the parent process about child process termination?
+
+The kernel notifies the parent by sending the SIGCHLD to the parent.
+
+
+
+How the waitpid() is different from wait()?
+
+The waitpid() is a non-blocking version of the wait() function.
+It also supports using library routine (e.g. system()) to wait a child process without messing up with other children processes for which the process has not waited.
+
+
+
+True or False? The wait() system call won't return until the child process has run and exited
+
+True in most cases though there are cases where wait() returns before the child exits.
+
+
Explain the exec() system call
+
+It transforms the current running program into another program.
+Given the name of an executable and some arguments, it loads the code and static data from the specified executable and overwrites its current code segment and current static code data. After initializing its memory space (like stack and heap) the OS runs the program passing any arguments as the argv of that process.
+
+
+
+True or False? A successful call to exec() never returns
+
+True
+Since a succesful exec replace the current process, it can't return anything to the process that made the call.
@@ -4022,18 +4139,9 @@ Not enough memory to create a new process
-What system call is used for creating a new process?
-
+What system calls are used for creating a new process?
-
-What are the differences between exec() and fork()?
-
-
-
-Why do we need the wait system call?
-
-wait() is used by a parent process to wait for the child process to finish execution.
-If wait is not used by a parent process then a child process might become a zombie process.
+fork(), exec() and the wait() system call is also included in this workflow.
@@ -4081,6 +4189,18 @@ Notes:
What exactly the command alias x=y does?
+
+Why running a new program is done using the fork() and exec() system calls? why a different API wasn't developed where there is one call to run a new program?
+
+This way provides a lot of flexibility. It allows the shell for example, to run code after the call to fork() but before the call to exec(). Such code can be used to alter the environment of the program it about to run.
+
+
+
+Describe shortly what happens when you execute a command in the shell
+
+The shell figures out, using the PATH variable, where the executable of the command resides in the filesystem. It then calls fork() to create a new child process for running the command. Once the fork was executed successfully, it calls a variant of exec() to execute the command and finally, waits the command to finish using wait(). When the child completes, the shell returns from wait() and prints out the prompt again.
+
+
#### Linux Filesystem & Files
@@ -4247,7 +4367,7 @@ GPL v2
What is an operating system?
-There are many ways to answer that. For those who look for simplicity, the book "Operating Systems: Three Easy Pieces" offers nice version:
+From the book "Operating Systems: Three Easy Pieces":
"responsible for making it easy to run programs (even allowing you to seemingly run many at the same time), allowing programs to share memory, enabling programs to interact with devices, and other fun stuff like that".
@@ -4417,6 +4537,15 @@ Yes, it's a operating-system-level virtualization, where the kernel is shared an
## Ansible
+### Ansible Exercises
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+| My First Task | Tasks | [Exercise](exercises/ansible/my_first_task.md) | [Solution](exercises/ansible/solutions/my_first_task.md)
+| My First Playbook | Playbooks | [Exercise](exercises/ansible/my_first_playbook.md) | [Solution](exercises/ansible/solutions/my_first_playbook.md)
+
+### Ansible Self Assesment
+
Describe each of the following components in Ansible, including the relationship between them:
@@ -4438,7 +4567,7 @@ Role – Ansible roles allows you to group resources based on certain functional
-How Ansible is different from other Automation tools?
+How Ansible is different from other automation tools? (e.g. Chef, Puppet, etc.)
Ansible is:
@@ -4448,14 +4577,20 @@ Ansible is:
* Focus on simpleness and ease-of-use
+
+What are collections in Ansible?
+
+
True or False? Ansible follows the mutable infrastructure paradigm
-True.
+True. In immutable infrastructure approach, you'll replace infrastructure instead of modifying it.
+Ansible rather follows the mutable infrastructure paradigm where it allows you to change the configuration of different components, but this approach is not perfect and has its own disadvantges like "configuration drift" where different components may reach different state for different reasons.
True or False? Ansible uses declarative style to describe the expected end state
+
False. It uses a procedural style.
@@ -4464,9 +4599,18 @@ False. It uses a procedural style.
While it's possible to provision resources with Ansible, some prefer to use tools that follow immutable infrastructure paradigm.
Ansible doesn't saves state by default. So a task that creates 5 instances for example, when executed again will create additional 5 instances (unless
-additional check is implemented) while other tools will check if 5 instances exist. If only 4 exist, additional instance will be created.
+additional check is implemented) while other tools will check if 5 instances exist. If only 4 exist (by checking the state file for example), additional instance will be created.
+
+How do you list all modules and how can you see details on a specific module?
+
+1. Ansible online docs
+2. `ansible-doc -l` for list of modules and `ansible [module_name]` for detailed information on a specific module
+
+
+#### Ansible - Inventory
+
What is an inventory file and how do you define one?
@@ -4495,34 +4639,48 @@ You should use one when using external sources and especially when the hosts in
spun up and shut down, without you tracking every change in these sources.
-
-How do you list all modules and how can you see details on a specific module?
-
-1. Ansible online docs
-2. `ansible-doc -l` for list of modules and `ansible [module_name]` for detailed information on a specific module
-
+#### Ansible - Variables
-Write a task to create the directory ‘/tmp/new_directory’
+Modify the following task to use a variable instead of the value "zlib" and have "zlib" as the default in case the variable is not defined
```
-- name: Create a new directory
- file:
- path: "/tmp/new_directory"
- state: directory
+- name: Install a package
+ package:
+ name: "zlib"
+ state: present
+```
+
+
+```
+- name: Install a package
+ package:
+ name: "{{ package_name|default('zlib') }}"
+ state: present
```
-You want to run Ansible playbook only on specific minor version of your OS, how would you achieve that?
-
+How to make the variable "use_var" optional?
-
-What the "become" directive used for in Ansible?
-
+```
+- name: Install a package
+ package:
+ name: "zlib"
+ state: present
+ use: "{{ use_var }}"
+```
+
-
-What are facts? How to see all the facts of a certain host?
+
+With "default(omit)"
+```
+- name: Install a package
+ package:
+ name: "zlib"
+ state: present
+ use: "{{ use_var|default(omit) }}"
+```
@@ -4542,6 +4700,18 @@ spun up and shut down, without you tracking every change in these sources.
When given a written code, always inspect it thoroughly. If your answer is “this will fail” then you are right. We are using a fact (ansible_hostname), which is a gathered piece of information from the host we are running on. But in this case, we disabled facts gathering (gather_facts: no) so the variable would be undefined which will result in failure.
+
+You want to run Ansible playbook only on specific minor version of your OS, how would you achieve that?
+
+
+
+What the "become" directive used for in Ansible?
+
+
+
+What are facts? How to see all the facts of a certain host?
+
+
What would be the result of running the following task? How to fix it?
@@ -4822,20 +4992,11 @@ Gotenks = 32
Explain what Terraform is and how does it works
-Read [here](https://www.terraform.io/intro/index.html#what-is-terraform-)
+[Terraform.io](https://www.terraform.io/intro/index.html#what-is-terraform-): "Terraform is an infrastructure as code (IaC) tool that allows you to build, change, and version infrastructure safely and efficiently."
-What benefits infrastructure-as-code has?
-
-- fully automated process of provisioning, modifying and deleting your infrastructure
-- version control for your infrastructure which allows you to quickly rollback to previous versions
-- validate infrastructure quality and stability with automated tests and code reviews
-- makes infrastructure tasks less repetitive
-
-
-
-Why Terraform and not other technologies? (e.g. Ansible, Puppet, CloufFormation)
+Why one would prefer using Terraform and not other technologies? (e.g. Ansible, Puppet, CloufFormation)
A common *wrong* answer is to say that Ansible and Puppet are configuration management tools
and Terraform is a provisioning tool. While technically true, it doesn't mean Ansible and Puppet can't
@@ -4848,6 +5009,15 @@ The benefits of Terraform over the other tools:
* Ansible and Puppet are more procedural (you mention what to execute in each step) and Terraform is declarative since you describe the overall desired state and not per resource or task. You can give the example of going from 1 to 2 servers in each tool. In Terraform you specify 2, in Ansible and puppet you have to only provision 1 additional server so you need to explicitly make sure you provision only another one server.
+
+How do you structure your Terraform projects?
+
+terraform_directory
+ providers.tf -> List providers (source, version, etc.)
+ variables.tf -> any variable used in other files such as main.tf
+ main.tf -> Lists the resources
+
+
True or False? Terraform follows the mutable infrastructure paradigm
@@ -4859,38 +5029,15 @@ False. Terraform follows immutable infrastructure paradigm.
True
-
-Explain what is "Terraform configuration"
-A configuration is a root module along with a tree of child modules that are called as dependencies from the root module.
-
-
What is HCL?
HCL stands for Hashicorp Configuration Language. It is the language Hashicorp made to use as the configuration language for a number of its tools, including terraform.
-Explain each of the following:
+Explain what is "Terraform configuration"
- * Provider
- * Resource
- * Provisioner
-
- * Provider is any cloud based technology - github, aws, postgresql etc - which one can make an API call to with its unique terraform provider binary to provision available services and components.
- * Resources are the services and components you provision on these platforms.
- * Provisioner in terraform's lingo specifically refers to configuration tools like ansible or salt-stack which are used in combination with terraform to orchestrate a system.
-
-
-
-What terraform.tfstate file is used for?
-
-It keeps track of the IDs of created resources so that Terraform knows what it's managing.
-
-
-
-How do you rename an existing resource?
-
-terraform state mv
+A configuration is a root module along with a tree of child modules that are called as dependencies from the root module.
@@ -4908,6 +5055,202 @@ terraform state mv
terraform apply will provision the resources specified in the .tf files.
+#### Terraform - Resources
+
+
+What is a "resource"?
+
+HashiCorp: "Terraform uses resource blocks to manage infrastructure, such as virtual networks, compute instances, or higher-level components such as DNS records. Resource blocks represent one or more infrastructure objects in your Terraform configuration."
+
+
+
+Explain each part of the following line: `resource "aws_instance" "web_server" {...}`
+
+ - resource: keyword for defining a resource
+ - "aws_instance": the type of the resource
+ - "web_server": the name of the resource
+
+
+
+What is the ID of the following resource: `resource "aws_instance" "web_server" {...}`
+
+`aws_instance.web_server`
+
+
+
+True or False? Resource ID must be unique within a workspace
+
+True
+
+
+
+Explain each of the following in regards to resources
+
+ - Arguments
+ - Attributes
+ - Meta-arguments
+
+ - Arguments: resource specific configurations
+ - Attributes: values exposed by the resource in a form of `resource_type.resource_name.attribute_name`. They are set by the provider or API usually.
+ - Meta-arguments: Functions of Terraform to change resource's behaviour
+
+
+#### Terraform - Providers
+
+
+Explain what is a "provider"
+
+[terraform.io](https://www.terraform.io/docs/language/providers/index.html): "Terraform relies on plugins called "providers" to interact with cloud providers, SaaS providers, and other APIs...Each provider adds a set of resource types and/or data sources that Terraform can manage. Every resource type is implemented by a provider; without providers, Terraform can't manage any kind of infrastructure."
+
+
+
+What is the name of the provider in this case: `resource "libvirt_domain" "instance" {...}`
+
+libvirt
+
+
+#### Terraform - Variables
+
+
+What are Input Variables in Terraform? Why one should use them?
+
+Input variables serve as parameters to the module in Terraform. They allow you for example to define once the value of a variable and use that variable in different places in the module so next time you would want to change the value, you will change it in one place instead of changing the value in different places in the module.
+
+
+
+How to define variables?
+
+```
+variable "app_id" {
+ type = string
+ description = "The id of application"
+ default = "some_value"
+}
+```
+
+Usually they are defined in their own file (vars.tf for example).
+
+
+
+How variables are used in modules?
+
+They are referenced with `var.VARIABLE_NAME`
+
+vars.tf:
+
+```
+variable "memory" {
+ type = string
+ default "8192"
+}
+
+variable "cpu" {
+ type = string
+ default = "4"
+}
+```
+
+main.tf:
+
+```
+resource "libvirt_domain" "vm1" {
+ name = "vm1"
+ memory = var.memory
+ cpu = var.cpu
+}
+```
+
+
+
+How would you enforce users that use your variables to provide values with certain constraints? For example, a number greater than 1
+
+Using `validation` block
+
+```
+variable "some_var" {
+ type = number
+
+ validation {
+ condition = var.some_var > 1
+ error_message = "you have to specify a number greater than 1"
+ }
+
+}
+```
+
+
+
+What is the effect of setting variable as "sensitive"?
+
+It doesn't show its value when you run `terraform apply` or `terraform plan` but eventually it's still recorded in the state file.
+
+
+
+True or Fales? If an expression's result depends on a sensitive variable, it will be treated as sensitive as well
+
+True
+
+
+
+The same variable is defined in the following places:
+
+ - The file `terraform.tfvars`
+ - Environment variable
+ - Using `-var` or `-var-file`
+
+According to varaible precedence, which source will be used first?
+
+The order is:
+
+ - Environment variable
+ - The file `terraform.tfvars`
+ - Using `-var` or `-var-file`
+
+
+
+What other way is there to define lots of variables in more "simplified" way?
+
+Using `.tfvars` file which contains variable consists of simple variable names assignments this way:
+
+```
+x = 2
+y = "mario"
+z = "luigi"
+```
+
+
+#### Terraform - State
+
+
+What terraform.tfstate file is used for?
+
+It keeps track of the IDs of created resources so that Terraform knows what it's managing.
+
+
+
+How do you rename an existing resource?
+
+terraform state mv
+
+
+
+Why does it matter where you store the tfstate file? Where would you store it?
+
+ - tfstate contains credentials in plain text. You don't want to put it in publicly shared location
+ - tfstate shouldn't be modified concurrently so putting it in a shared location available for everyone with "write" permissions might lead to issues. (Terraform remote state doesn't has this problem).
+ - tfstate is in important file. As such, it might be better to put it in a location that has regular backups.
+
+As such, tfstate shouldn't be stored in git repositories. secured storage such as secured buckets, is a better option.
+
+
+
+Mention some best practices related to tfstate
+
+ - Don't edit it manually. tfstate was designed to be manipulated by terraform and not by users directly.
+ - Store it in secured location (since it can include credentials and sensitive data in general)
+ - Backup it regularly so you can roll-back easily when needed
+
+
How to write down a variable which changes by an external source or during terraform apply?
@@ -4915,11 +5258,17 @@ You use it this way: variable “my_var” {}
-Give an example of several Terraform best practices
+You've deployed a virtual machine with Terraform and you would like to pass data to it (or execute some commands). Which concept of Terraform would you use?
+
+[Provisioners](https://www.terraform.io/docs/language/resources/provisioners)
+#### Terraform - Provisioners
+
-Explain how implicit and explicit dependencies work in Terraform
+What are "Provisioners"? What they are used for?
+
+Provisioners used to execute actions on local or remote machine. It's extremely useful in case you provisioned an instance and you want to make a couple of changes in the machine you've created without manually ssh into it after Terraform finished to run and manually run them.
@@ -5263,14 +5612,13 @@ Because each container has its own writable container layer, and all changes are
### Kubernetes Exercises
-#### Developer & Regular User Path
+#### Developer & "Regular" User Path
|Name|Topic|Objective & Instructions|Solution|Comments|
|--------|--------|------|----|----|
| My First Pod | Pods | [Exercise](exercises/kubernetes/pods_01.md) | [Solution](exercises/kubernetes/solutions/pods_01_solution.md)
| Creating a service | Service | [Exercise](exercises/kubernetes/services_01.md) | [Solution](exercises/kubernetes/solutions/services_01_solution.md)
-
### Kubernetes Self Assesment
@@ -5295,8 +5643,18 @@ At a minimum, a cluster contains a worker node and a master node."
Read more [here](https://www.redhat.com/en/topics/containers/what-is-a-kubernetes-cluster)
+
+Do you have experience with deploying a Kubernetes cluster? If so, can you describe the process in high-level?
+
+1. Create multiple instances you will use as Kubernetes nodes/workers. Create also an instance to act as the Master. The instances can be part of the cloud or virtual machines on physical hosts.
+2.
+
+
When or why NOT to use Kubernetes?
+
+ - If you deploy applications using container and you need to manage scaling, rolling out updates, etc. You should use Kubernetes
+ - If you manage low level infrastructure or baremetals, Kubernetes is probably not what you need or want
#### Kubernetes Nodes
@@ -5326,9 +5684,10 @@ The workers are the nodes which run the applications and workloads.
What is kubectl?
-
Kubectl is the Kubernetes command line tool that allows you to run commands against Kubernetes clusters. For example, you can use kubectl to deploy applications, inspect and manage cluster resources, and view logs.
+
+
Which command you run to view your nodes?
@@ -5358,7 +5717,7 @@ False. A Kubernetes cluster consists of at least 1 master and can have 0 workers
* Container runtime - the engine runs the containers (Podman, Docker, ...)
-#### Kubernetes Pod
+#### Kubernetes - Pod
Explain what is a pod
@@ -5375,7 +5734,7 @@ A Pod is a group of one or more containers, with shared storage and network reso
How many containers can a pod contain?
-Multiple containers but in most cases it would be one container per pod.
+Multiple containers but in most cases it would probably be one container per pod.
@@ -5385,7 +5744,19 @@ It means they would eventually die and pods are unable to heal so it is recommen
-Which command you run to view all pods running on all namespaces?
+True or False? By default, pods are isolated. This means they are unable to receive traffic from any source
+
+False. By default, pods are non-isolated = pods accent traffic from any source.
+
+
+
+How to list the pods in the current namespace?
+
+`kubectl get po`
+
+
+
+How view all the pods running in all the namespaces?
`kubectl get pods --all-namespaces`
@@ -5413,10 +5784,6 @@ Deployments can scale the number of replica pods, enable rollout of updated cod
A Deployment is a declarative statement for the desired state for Pods and Replica Sets.
-
-Describe the process of a deployment in high level
-
-
How to create a deployment?
@@ -5467,7 +5834,7 @@ The pod related to the deployment will terminate and the replicaset will be remo
Using a Service.
-#### Kubernetes Service
+#### Kubernetes - Service
What is a Service in Kubernetes?
@@ -5544,7 +5911,7 @@ spec:
Ingress
-#### Kubernetes Ingress
+#### Kubernetes - Ingress
What is Ingress?
@@ -5658,7 +6025,42 @@ spec:
True
-#### Kubernetes Configuration File
+
+Which Kubernetes concept would you use to control traffic flow at the IP address or port level?
+
+Network Policies
+
+
+#### Kubernetes - Network Policies
+
+
+Explain Network Policies
+
+[kubernetes.io](https://kubernetes.io/docs/concepts/services-networking/network-policies): "NetworkPolicies are an application-centric construct which allow you to specify how a pod is allowed to communicate with various network "entities"..."
+
+In simpler words, Network Policies specify how pods are allowed/disallowed to communicate with each other and/or other network endpoints.
+
+
+
+What are some use cases for using Network Policies?
+
+ - Security: You want to prevent from everyone to communicate with a certain pod for security reasons
+ - Controling network traffic: You would like to deny network flow between two specific nodes
+
+
+
+True or False? If no network policies are applied to a pod, then no connections to or from it are allowed
+
+False. By default pods are non-isolated.
+
+
+
+In case of two pods, if there is an egress policy on the source denining traffic and ingress policy on the destination that allows traffic then, traffic will be allowed or denied?
+
+Denied. Both source and destination policies has to allow traffic for it to be allowed.
+
+
+#### Kubernetes - Configuration File
Which parts a configuration file has?
@@ -6784,6 +7186,17 @@ def find_triplets_sum_to_zero(li):
## Python
+### Python Exercises
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+| Identify the data type | Data Types | [Exercise](exercises/python/data_types.md) | [Solution](exercises/python/solutions/data_types_solution.md)
+| Identify the data type - Advanced | Data Types | [Exercise](exercises/python/advanced_data_types.md) | [Solution](exercises/python/solutions/advanced_data_types_solution.md)
+| Reverse String | Strings | [Exercise](exercises/python/reverse_string.md) | [Solution](exercises/python/solutions/reverse_string.md)
+| Compress String | Strings | [Exercise](exercises/python/compress_string.md) | [Solution](exercises/python/solutions/compress_string.md)
+
+### Python Self Assessment
+
What are some characteristics of the Python programming language?
@@ -6831,17 +7244,7 @@ The immutable data types are:
Frozenset
-
-What is a tuple in Python? What is it used for?
-
-A tuple is a built-in data type in Python. It's used for storing multiple items in a single variable.
-
-
-
-List, like a tuple, is also used for storing multiple items. What is then, the difference between a tuple and a list?
-
-List, as opposed to a tuple, is a mutable data type. It means we can modify it and at items to it.
-
+#### Python - Booleans
What is the result of each of the following?
@@ -6857,6 +7260,34 @@ List, as opposed to a tuple, is a mutable data type. It means we can modify it a
* TypeError
+
+What is the result of `bool("")`? What about `bool(" ")`? Explain
+
+bool("") -> evaluates to False
+bool(" ") -> evaluates to True
+
+
+
+What is the result of running [] is not []? explain the result
+
+It evaluates to True.
+The reason is that the two created empty list are different objects. `x is y` only evaluates to true when x and y are the same object.
+
+
+
+What is the result of running True-True?
+
+0
+
+
+#### Python - Strings
+
+
+True or False? String is an immutable data type in Python
+
+True
+
+
What is the result of of each of the following?
@@ -6873,20 +7304,6 @@ List, as opposed to a tuple, is a mutable data type. It means we can modify it a
* ""
-
-What is the result of `bool("")`? What about `bool(" ")`? Explain
-
-bool("") -> evaluates to False
-bool(" ") -> evaluates to True
-
-
-
-What is the result of running [] is not []? explain the result
-
-It evaluates to True.
-The reason is that the two created empty list are different objects. `x is y` only evaluates to true when x and y are the same object.
-
-
Improve the following code:
@@ -6909,6 +7326,8 @@ if lower(input("Insert a character: ")[0]) in "aieou": # Takes care of multiple
```
+#### Python - Functions
+
How to define a function with Python?
Using the `def` keyword. For Examples:
@@ -6933,6 +7352,8 @@ def my_function():
You can then assign a function to a variables like this `x = my_function` or you can return functions as return values like this `return my_function`
+#### Python - OOP
+
Explain inheritance and how to use it in Python
@@ -7248,7 +7669,19 @@ print("{0:.3f}".format(sum(li)/len(li)))
```
-#### Python Lists
+#### Python - Lists
+
+
+What is a tuple in Python? What is it used for?
+
+A tuple is a built-in data type in Python. It's used for storing multiple items in a single variable.
+
+
+
+List, like a tuple, is also used for storing multiple items. What is then, the difference between a tuple and a list?
+
+List, as opposed to a tuple, is a mutable data type. It means we can modify it and at items to it.
+How to add the number 2 to the list x = [1, 2, 3]
@@ -7540,7 +7973,7 @@ set([food for bro in x for food in bro['food']])
```
-#### Python Dictionaries
+#### Python - Dictionaries
How to create a dictionary?
@@ -7826,24 +8259,9 @@ Detailed answer can be found here: http://codingshell.com/python-all-string-perm
-How to reverse a string? (e.g. pizza -> azzip)
+If x = "pizza", what would be the result of x[::-1]?
-The correct way is:
-
-```
-my_string[::-1]
-```
-
-A more visual way is:
-Careful: this is very slow
-
-```
-def reverse_string(string):
- temp = ""
- for char in string:
- temp = char + temp
- return temp
-```
+It will reverse the string, so x would be equal to `azzip`.
@@ -8787,7 +9205,6 @@ This is a great article about Octopus merge: http://www.freblogg.com/2016/12/git
## Go
-
What are some characteristics of the Go programming language?
@@ -9147,6 +9564,14 @@ as key-value pair, document-oriented, etc.
## OpenShift
+### OpenShift Exercises
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+| My First Project | Projects | [Exercise](exercises/openshift/projects_101.md) | [Solution](exercises/openshift/solutions/projects_101.md)
+
+### OpenShift Self Assessment
+
What is OpenShift?
@@ -9187,6 +9612,21 @@ The Scheduler.
Application high availability by spreading pod replicas between worker nodes
+## OpenShift - Projects
+
+
+What is a project in OpenShift?
+
+A project in OpenShift is a Kubernetes namespace with annotations.
+In simpler words, think about it as an isolated environment for users to manage and organize their resources (like Pods, Deployments, Service, etc.).
+
+
+
+How to list all projects? What the "STATUS" column means in projects list output?
+
+`oc get projects` will list all projects. The "STATUS" column can be used to see which projects are currently active.
+
+
## OpenShift - Images
@@ -9322,6 +9762,26 @@ False. It can run on any node.
4. Router proxies the request to the internal pod
+#### OpenShift - Security
+
+
+What are "Security Context Constraints"?
+
+From [OpenShift Docs](https://docs.openshift.com/container-platform/4.7/authentication/managing-security-context-constraints.html): "Similar to the way that RBAC resources control user access, administrators can use security context constraints (SCCs) to control permissions for pods".
+
+
+
+How to add the ability for the user `user1` to view the project `wonderland` assuming you are authorized to do so
+
+oc adm policy add-role-to-user view user1 -n wonderland
+
+
+
+How to check what is the current context?
+
+`oc whoami --show-context`
+
+
#### OpenShift - Misc
@@ -9414,11 +9874,19 @@ done
## SQL
+### SQL Exercises
+
+|Name|Topic|Objective & Instructions|Solution|Comments|
+|--------|--------|------|----|----|
+| Functions vs. Comparisons | Query Improvements | [Exercise](exercises/sql/improve_query.md) | [Solution](exercises/sql/solutions/improve_query.md)
+
+### SQL Self Assessment
+
-What does SQL stand for?
-
-Structured Query Language
+What is SQL?
+SQL (Structured Query Language) is a standard language for relational databases (like MySQL, MariaDB, ...).
+It's used for reading, updating, removing and creating data in a relational database.
@@ -9430,40 +9898,6 @@ unstructured, and the data storage can vary depending on how the NoSQL DB is set
as key-value pair, document-oriented, etc.
-
-What does it mean when a database is ACID compliant?
-
-ACID stands for Atomicity, Consistency, Isolation, Durability. In order to be ACID compliant, the database much meet each of the four criteria
-
-**Atomicity** - When a change occurs to the database, it should either succeed or fail as a whole.
-
-For example, if you were to update a table, the update should completely execute. If it only partially executes, the
-update is considered failed as a whole, and will not go through - the DB will revert back to it's original
-state before the update occurred. It should also be mentioned that Atomicity ensures that each
-transaction is completed as it's own stand alone "unit" - if any part fails, the whole statement fails.
-
-**Consistency** - any change made to the database should bring it from one valid state into the next.
-
-For example, if you make a change to the DB, it shouldn't corrupt it. Consistency is upheld by checks and constraints that
-are pre-defined in the DB. For example, if you tried to change a value from a string to an int when the column
-should be of datatype string, a consistent DB would not allow this transaction to go through, and the action would
-not be executed
-
-**Isolation** - this ensures that a database will never be seen "mid-update" - as multiple transactions are running at
-the same time, it should still leave the DB in the same state as if the transactions were being run sequentially.
-
-For example, let's say that 20 other people were making changes to the database at the same time. At the
-time you executed your query, 15 of the 20 changes had gone through, but 5 were still in progress. You should
-only see the 15 changes that had completed - you wouldn't see the database mid-update as the change goes through.
-
-**Durability** - Once a change is committed, it will remain committed regardless of what happens
-(power failure, system crash, etc.). This means that all completed transactions
-must be recorded in non-volatile memory.
-
-Note that SQL is by nature ACID compliant. Certain NoSQL DB's can be ACID compliant depending on
-how they operate, but as a general rule of thumb, NoSQL DB's are not considered ACID compliant
-
-
When is it best to use SQL? NoSQL?
@@ -9478,21 +9912,7 @@ Additionally, since NoSQL does not adhere to the strict table with columns and r
that Relational Databases require, you can store different data types together.
-
-What is a Cartesian Product?
-
-A Cartesian product is when all rows from the first table are joined to all rows in the second
-table. This can be done implicitly by not defining a key to join, or explicitly by
-calling a CROSS JOIN on two tables, such as below:
-
-Select * from customers **CROSS JOIN** orders;
-
-Note that a Cartesian product can also be a bad thing - when performing a join
-on two tables in which both do not have unique keys, this could cause the returned information
-to be incorrect.
-
-
-##### SQL Specific Questions
+##### Practical SQL - Basics
For these questions, we will be using the Customers and Orders tables shown below:
@@ -9587,6 +10007,29 @@ The Sum of all the purchases of cat food weren't readily available, so we used a
the pseudo table to retrieve the sum of the prices spent by each customer, then join the table normally.
+
+Which of the following queries would you use?
+
+```
+SELECT count(*) SELECT count(*)
+FROM shawarma_purchases FROM shawarma_purchases
+WHERE vs. WHERE
+ YEAR(purchased_at) == '2017' purchased_at >= '2017-01-01' AND
+ purchased_at <= '2017-31-12'
+```
+
+
+```
+SELECT count(*)
+FROM shawarma_purchases
+WHERE
+ purchased_at >= '2017-01-01' AND
+ purchased_at <= '2017-31-12'
+```
+
+When you use a function (`YEAR(purchased_at)`) it has to scan the whole database as opposed to using indexes and basically the column as it is, in its natural state.
+
+
## Azure
@@ -10061,6 +10504,22 @@ You can read about TripleO right [here](https://docs.openstack.org/tripleo-docs/
* External Network - used for public communication. Any IP address in this network is accessible by anyone on the internet
+
+In which order should you remove the following entities:
+
+ - Network
+ - Port
+ - Router
+ - Subnet
+
+ - Port
+ - Subnet
+ - Router
+ - Network
+
+There are many reasons for that. One for example: you can't remove router if there are active ports assigned to it.
+
+
What is a provider network?
@@ -10133,13 +10592,13 @@ Not by default. Object Storage API limits the maximum to 5GB per object but it c
Explain the following in regards to Swift:
- * Container
- * Account
- * Object
+ - Container
+ - Account
+ - Object
- * Container - Defines a namespace for objects.
- * Account - Defines a namespace for containers
- * Object - Data content (e.g. image, document, ...)
+ - Container - Defines a namespace for objects.
+ - Account - Defines a namespace for containers
+ - Object - Data content (e.g. image, document, ...)
@@ -10172,38 +10631,38 @@ False. Two objects can have the same name if they are in different containers.
Can you describe the following concepts in regards to Keystone?
- * Role
- * Tenant/Project
- * Service
- * Endpoint
- * Token
+ - Role
+ - Tenant/Project
+ - Service
+ - Endpoint
+ - Token
- * Role - A list of rights and privileges determining what a user or a project can perform
- * Tenant/Project - Logical representation of a group of resources isolated from other groups of resources. It can be an account, organization, ...
- * Service - An endpoint which the user can use for accessing different resources
- * Endpoint - a network address which can be used to access a certain OpenStack service
- * Token - Used for access resources while describing which resources can be accessed by using a scope
+ - Role - A list of rights and privileges determining what a user or a project can perform
+ - Tenant/Project - Logical representation of a group of resources isolated from other groups of resources. It can be an account, organization, ...
+ - Service - An endpoint which the user can use for accessing different resources
+ - Endpoint - a network address which can be used to access a certain OpenStack service
+ - Token - Used for access resources while describing which resources can be accessed by using a scope
What are the properties of a service? In other words, how a service is identified?
Using:
- * Name
- * ID number
- * Type
- * Description
+ - Name
+ - ID number
+ - Type
+ - Description
Explain the following:
- * PublicURL
- * InternalURL
- * AdminURL
+ - PublicURL
+ - InternalURL
+ - AdminURL
- * PublicURL - Publicly accessible through public internet
- * InternalURL - Used for communication between services
- * AdminURL - Used for administrative management
+ - PublicURL - Publicly accessible through public internet
+ - InternalURL - Used for communication between services
+ - AdminURL - Used for administrative management
@@ -11067,6 +11526,18 @@ DNS (Domain Name Systems) is a protocol used for converting domain names into IP
As you know computer networking is done with IP addresses (layer 3 of the OSI model) but for as humans it's hard to remember IP addresses, it's much easier to remember names. This why we need something such as DNS to convert any domain name we type into an IP address. You can think on DNS as a huge phonebook or database where each corresponding name has an IP.
+
+What is DNS resolution?
+
+The process of translating IP addresses to domain names.
+
+
+
+What is a DNS record?
+
+A mapping between domain name and an IP address.
+
+
How DNS works?
@@ -11215,9 +11686,24 @@ It's an architecture in which data is and retrieved from a single, non-shared, s
## Misc
-What is a server? What is a client?
+What happens when you type in a URL in an address bar in a browser?
-A computer which serves data from itself to the client.
+1. The browser searches for the record of the domain name IP address in the DNS in the following order:
+ * Browser cache
+ * Operating system cache
+ * The DNS server configured on the user's system (can be ISP DNS, public DNS, ...)
+
+2. If it couldn't find a DNS record locally, a full DNS resolution is started.
+
+3. It connects to the server using the TCP protocol
+
+4. The browser sends an HTTP request to the server
+
+5. The server sends an HTTP response back to the browser
+
+6. The browser renders the response (e.g. HTML)
+
+7. The browser then sends subsequent requests as needed to the server to get the embedded links, javascript, images in the HTML and then steps 3 to 5 are repeated.
@@ -11664,7 +12150,11 @@ Relax, there is no wrong or right answer here...I think.
-How would you describe a good leadership? What makes a good boss for you?
+How would you describe a good leadership?
+
+
+
+Describe yourself in one word
@@ -11860,6 +12350,40 @@ Not only this will tell you what is expected from you, it will also provide big
## Databases
+
+What does it mean when a database is ACID compliant?
+
+ACID stands for Atomicity, Consistency, Isolation, Durability. In order to be ACID compliant, the database much meet each of the four criteria
+
+**Atomicity** - When a change occurs to the database, it should either succeed or fail as a whole.
+
+For example, if you were to update a table, the update should completely execute. If it only partially executes, the
+update is considered failed as a whole, and will not go through - the DB will revert back to it's original
+state before the update occurred. It should also be mentioned that Atomicity ensures that each
+transaction is completed as it's own stand alone "unit" - if any part fails, the whole statement fails.
+
+**Consistency** - any change made to the database should bring it from one valid state into the next.
+
+For example, if you make a change to the DB, it shouldn't corrupt it. Consistency is upheld by checks and constraints that
+are pre-defined in the DB. For example, if you tried to change a value from a string to an int when the column
+should be of datatype string, a consistent DB would not allow this transaction to go through, and the action would
+not be executed
+
+**Isolation** - this ensures that a database will never be seen "mid-update" - as multiple transactions are running at
+the same time, it should still leave the DB in the same state as if the transactions were being run sequentially.
+
+For example, let's say that 20 other people were making changes to the database at the same time. At the
+time you executed your query, 15 of the 20 changes had gone through, but 5 were still in progress. You should
+only see the 15 changes that had completed - you wouldn't see the database mid-update as the change goes through.
+
+**Durability** - Once a change is committed, it will remain committed regardless of what happens
+(power failure, system crash, etc.). This means that all completed transactions
+must be recorded in non-volatile memory.
+
+Note that SQL is by nature ACID compliant. Certain NoSQL DB's can be ACID compliant depending on
+how they operate, but as a general rule of thumb, NoSQL DB's are not considered ACID compliant
+
+
What is sharding?
diff --git a/exercises/ansible/my_first_playbook.md b/exercises/ansible/my_first_playbook.md
new file mode 100644
index 0000000..d4c188a
--- /dev/null
+++ b/exercises/ansible/my_first_playbook.md
@@ -0,0 +1,6 @@
+## Ansible - My First Playbook
+
+1. Write a playbook that will:
+ a. Install the package zlib
+ b. Create the file `/tmp/some_file`
+2. Run the playbook on a remote host
diff --git a/exercises/ansible/my_first_task.md b/exercises/ansible/my_first_task.md
new file mode 100644
index 0000000..086c6f8
--- /dev/null
+++ b/exercises/ansible/my_first_task.md
@@ -0,0 +1,3 @@
+## Ansible - My First Task
+
+1. Write a task to create the directory ‘/tmp/new_directory’
diff --git a/exercises/ansible/solutions/my_first_playbook.md b/exercises/ansible/solutions/my_first_playbook.md
new file mode 100644
index 0000000..ab1761e
--- /dev/null
+++ b/exercises/ansible/solutions/my_first_playbook.md
@@ -0,0 +1,28 @@
+## My first playbook - Solution
+
+1. `vi first_playbook.yml`
+
+```
+- name: Install zlib and create a file
+ hosts: some_remote_host
+ tasks:
+ - name: Install zlib
+ package:
+ name: zlib
+ state: present
+ become: yes
+ - name: Create the file /tmp/some_file
+ path: '/tmp/some_file'
+ state: touch
+```
+
+2. First, edit the inventory file: `vi /etc/ansible/hosts`
+
+```
+[some_remote_host]
+some.remoted.host.com
+```
+
+Run the playbook
+
+`ansible-playbook first_playbook.yml`
diff --git a/exercises/ansible/solutions/my_first_task.md b/exercises/ansible/solutions/my_first_task.md
new file mode 100644
index 0000000..9eb4186
--- /dev/null
+++ b/exercises/ansible/solutions/my_first_task.md
@@ -0,0 +1,8 @@
+## My First Task - Solution
+
+```
+- name: Create a new directory
+ file:
+ path: "/tmp/new_directory"
+ state: directory
+```
diff --git a/exercises/devops/deploy_to_kubernetes.md b/exercises/devops/deploy_to_kubernetes.md
new file mode 100644
index 0000000..965605e
--- /dev/null
+++ b/exercises/devops/deploy_to_kubernetes.md
@@ -0,0 +1,5 @@
+## Deploy to Kubernetes
+
+* Write a pipeline that will deploy an "hello world" web app to Kubernete
+* The CI/CD system (where the pipeline resides) and the Kubernetes cluster should be on separate systems
+* The web app should be accessible remotely and only with HTTPS
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/Jenkinsfile b/exercises/devops/solutions/deploy_to_kubernetes/Jenkinsfile
new file mode 100644
index 0000000..6af14a5
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/Jenkinsfile
@@ -0,0 +1,45 @@
+pipeline {
+
+ agent any
+
+ stages {
+
+ stage('Checkout Source') {
+ steps {
+ git url:'https://github.com//.git',
+ // credentialsId: 'creds_github',
+ branch:'master'
+ }
+ }
+
+ stage("Build image") {
+ steps {
+ script {
+ myapp = docker.build("/helloworld:${env.BUILD_ID}")
+ }
+ }
+ }
+
+ stage("Push image") {
+ steps {
+ script {
+ docker.withRegistry('https://registry.hub.docker.com', 'dockerhub') {
+ myapp.push("latest")
+ myapp.push("${env.BUILD_ID}")
+ }
+ }
+ }
+ }
+
+
+ stage('Deploy App') {
+ steps {
+ script {
+ sh 'ansible-playbook deploy.yml'
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/README.md b/exercises/devops/solutions/deploy_to_kubernetes/README.md
new file mode 100644
index 0000000..61724b6
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/README.md
@@ -0,0 +1,15 @@
+## Deploy to Kubernetes
+
+Note: this exercise can be solved in various ways. The solution described here is just one possible way.
+
+1. Install Jenkins on one system (follow up the standard Jenkins installation procedure)
+2. Deploy Kubernetes on a remote host (minikube can be an easy way to achieve it)
+3. Create a simple web app or [page](html)
+
+4. Create Kubernetes [resoruces](helloworld.yml) - Deployment, Service and Ingress (for HTTPS access)
+5. Create an [Ansible inventory](inventory) and insert the address of the Kubernetes cluster
+6. Write [Ansible playbook](deploy.yml) to deploy the Kubernetes resources and also generate
+7. Create a [pipeline](Jenkinsfile)
+
+8. Run the pipeline :)
+9. Try to access the web app remotely
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/deploy.yml b/exercises/devops/solutions/deploy_to_kubernetes/deploy.yml
new file mode 100644
index 0000000..0aa9635
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/deploy.yml
@@ -0,0 +1,42 @@
+- name: Apply Kubernetes YAMLs
+ hosts: kubernetes
+ tasks:
+ - name: Ensure SSL related directories exist
+ file:
+ path: "{{ item }}"
+ state: directory
+ loop:
+ - "/etc/ssl/crt"
+ - "/etc/ssl/csr"
+ - "/etc/ssl/private"
+
+ - name: Generate an OpenSSL private key.
+ openssl_privatekey:
+ path: /etc/ssl/private/privkey.pem
+
+ - name: generate openssl certficate signing requests
+ openssl_csr:
+ path: /etc/ssl/csr/hello-world.app.csr
+ privatekey_path: /etc/ssl/private/privkey.pem
+ common_name: hello-world.app
+
+ - name: Generate a Self Signed OpenSSL certificate
+ openssl_certificate:
+ path: /etc/ssl/crt/hello-world.app.crt
+ privatekey_path: /etc/ssl/private/privkey.pem
+ csr_path: /etc/ssl/csr/hello-world.app.csr
+ provider: selfsigned
+
+ - name: Create k8s secret
+ command: "kubectl create secret tls tls-secret --cert=/etc/ssl/crt/hello-world.app.crt --key=/etc/ssl/private/privkey.pem"
+ register: result
+ failed_when:
+ - result.rc == 2
+
+ - name: Deploy web app
+ k8s:
+ state: present
+ definition: "{{ lookup('file', './helloworld.yml') }}"
+ kubeconfig: '/home/abregman/.kube/config'
+ namespace: 'default'
+ wait: true
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/helloworld.yml b/exercises/devops/solutions/deploy_to_kubernetes/helloworld.yml
new file mode 100644
index 0000000..de120f2
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/helloworld.yml
@@ -0,0 +1,65 @@
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: hello-blue-whale
+spec:
+ replicas: 3
+ selector:
+ matchLabels:
+ app: hello-world-app
+ version: blue
+ template:
+ metadata:
+ name: hello-blue-whale-pod
+ labels:
+ app: hello-world-app
+ version: blue
+ spec:
+ containers:
+ - name: hello-whale-container
+ image: abregman2/helloworld:latest
+ imagePullPolicy: Always
+ ports:
+ - containerPort: 80
+ - containerPort: 443
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: hello-world
+ labels:
+ app: hello-world-app
+spec:
+ ports:
+ - port: 80
+ targetPort: 80
+ protocol: TCP
+ name: http
+ selector:
+ app: hello-world-app
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: example-ingress
+ annotations:
+ cert-manager.io/cluster-issuer: selfsigned-issuer
+ nginx.ingress.kubernetes.io/rewrite-target: /
+ kubernetes.io/ingress.class: nginx
+spec:
+ tls:
+ - hosts:
+ - hello-world.app
+ secretName: shhh
+ rules:
+ - host: hello-world.app
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: hello-world
+ port:
+ number: 80
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/html/css/normalize.css b/exercises/devops/solutions/deploy_to_kubernetes/html/css/normalize.css
new file mode 100644
index 0000000..81c6f31
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/html/css/normalize.css
@@ -0,0 +1,427 @@
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
\ No newline at end of file
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/html/css/skeleton.css b/exercises/devops/solutions/deploy_to_kubernetes/html/css/skeleton.css
new file mode 100644
index 0000000..f28bf6c
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/html/css/skeleton.css
@@ -0,0 +1,418 @@
+/*
+* Skeleton V2.0.4
+* Copyright 2014, Dave Gamache
+* www.getskeleton.com
+* Free to use under the MIT license.
+* http://www.opensource.org/licenses/mit-license.php
+* 12/29/2014
+*/
+
+
+/* Table of contents
+––––––––––––––––––––––––––––––––––––––––––––––––––
+- Grid
+- Base Styles
+- Typography
+- Links
+- Buttons
+- Forms
+- Lists
+- Code
+- Tables
+- Spacing
+- Utilities
+- Clearing
+- Media Queries
+*/
+
+
+/* Grid
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+.container {
+ position: relative;
+ width: 100%;
+ max-width: 960px;
+ margin: 0 auto;
+ padding: 0 20px;
+ box-sizing: border-box; }
+.column,
+.columns {
+ width: 100%;
+ float: left;
+ box-sizing: border-box; }
+
+/* For devices larger than 400px */
+@media (min-width: 400px) {
+ .container {
+ width: 85%;
+ padding: 0; }
+}
+
+/* For devices larger than 550px */
+@media (min-width: 550px) {
+ .container {
+ width: 80%; }
+ .column,
+ .columns {
+ margin-left: 4%; }
+ .column:first-child,
+ .columns:first-child {
+ margin-left: 0; }
+
+ .one.column,
+ .one.columns { width: 4.66666666667%; }
+ .two.columns { width: 13.3333333333%; }
+ .three.columns { width: 22%; }
+ .four.columns { width: 30.6666666667%; }
+ .five.columns { width: 39.3333333333%; }
+ .six.columns { width: 48%; }
+ .seven.columns { width: 56.6666666667%; }
+ .eight.columns { width: 65.3333333333%; }
+ .nine.columns { width: 74.0%; }
+ .ten.columns { width: 82.6666666667%; }
+ .eleven.columns { width: 91.3333333333%; }
+ .twelve.columns { width: 100%; margin-left: 0; }
+
+ .one-third.column { width: 30.6666666667%; }
+ .two-thirds.column { width: 65.3333333333%; }
+
+ .one-half.column { width: 48%; }
+
+ /* Offsets */
+ .offset-by-one.column,
+ .offset-by-one.columns { margin-left: 8.66666666667%; }
+ .offset-by-two.column,
+ .offset-by-two.columns { margin-left: 17.3333333333%; }
+ .offset-by-three.column,
+ .offset-by-three.columns { margin-left: 26%; }
+ .offset-by-four.column,
+ .offset-by-four.columns { margin-left: 34.6666666667%; }
+ .offset-by-five.column,
+ .offset-by-five.columns { margin-left: 43.3333333333%; }
+ .offset-by-six.column,
+ .offset-by-six.columns { margin-left: 52%; }
+ .offset-by-seven.column,
+ .offset-by-seven.columns { margin-left: 60.6666666667%; }
+ .offset-by-eight.column,
+ .offset-by-eight.columns { margin-left: 69.3333333333%; }
+ .offset-by-nine.column,
+ .offset-by-nine.columns { margin-left: 78.0%; }
+ .offset-by-ten.column,
+ .offset-by-ten.columns { margin-left: 86.6666666667%; }
+ .offset-by-eleven.column,
+ .offset-by-eleven.columns { margin-left: 95.3333333333%; }
+
+ .offset-by-one-third.column,
+ .offset-by-one-third.columns { margin-left: 34.6666666667%; }
+ .offset-by-two-thirds.column,
+ .offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
+
+ .offset-by-one-half.column,
+ .offset-by-one-half.columns { margin-left: 52%; }
+
+}
+
+
+/* Base Styles
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+/* NOTE
+html is set to 62.5% so that all the REM measurements throughout Skeleton
+are based on 10px sizing. So basically 1.5rem = 15px :) */
+html {
+ font-size: 62.5%; }
+body {
+ font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
+ line-height: 1.6;
+ font-weight: 400;
+ font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #222; }
+
+
+/* Typography
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ margin-bottom: 2rem;
+ font-weight: 300; }
+h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
+h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
+h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
+h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
+h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
+h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
+
+/* Larger than phablet */
+@media (min-width: 550px) {
+ h1 { font-size: 5.0rem; }
+ h2 { font-size: 4.2rem; }
+ h3 { font-size: 3.6rem; }
+ h4 { font-size: 3.0rem; }
+ h5 { font-size: 2.4rem; }
+ h6 { font-size: 1.5rem; }
+}
+
+p {
+ margin-top: 0; }
+
+
+/* Links
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+a {
+ color: #1EAEDB; }
+a:hover {
+ color: #0FA0CE; }
+
+
+/* Buttons
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+.button,
+button,
+input[type="submit"],
+input[type="reset"],
+input[type="button"] {
+ display: inline-block;
+ height: 38px;
+ padding: 0 30px;
+ color: #555;
+ text-align: center;
+ font-size: 11px;
+ font-weight: 600;
+ line-height: 38px;
+ letter-spacing: .1rem;
+ text-transform: uppercase;
+ text-decoration: none;
+ white-space: nowrap;
+ background-color: transparent;
+ border-radius: 4px;
+ border: 1px solid #bbb;
+ cursor: pointer;
+ box-sizing: border-box; }
+.button:hover,
+button:hover,
+input[type="submit"]:hover,
+input[type="reset"]:hover,
+input[type="button"]:hover,
+.button:focus,
+button:focus,
+input[type="submit"]:focus,
+input[type="reset"]:focus,
+input[type="button"]:focus {
+ color: #333;
+ border-color: #888;
+ outline: 0; }
+.button.button-primary,
+button.button-primary,
+input[type="submit"].button-primary,
+input[type="reset"].button-primary,
+input[type="button"].button-primary {
+ color: #FFF;
+ background-color: #33C3F0;
+ border-color: #33C3F0; }
+.button.button-primary:hover,
+button.button-primary:hover,
+input[type="submit"].button-primary:hover,
+input[type="reset"].button-primary:hover,
+input[type="button"].button-primary:hover,
+.button.button-primary:focus,
+button.button-primary:focus,
+input[type="submit"].button-primary:focus,
+input[type="reset"].button-primary:focus,
+input[type="button"].button-primary:focus {
+ color: #FFF;
+ background-color: #1EAEDB;
+ border-color: #1EAEDB; }
+
+
+/* Forms
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+input[type="email"],
+input[type="number"],
+input[type="search"],
+input[type="text"],
+input[type="tel"],
+input[type="url"],
+input[type="password"],
+textarea,
+select {
+ height: 38px;
+ padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
+ background-color: #fff;
+ border: 1px solid #D1D1D1;
+ border-radius: 4px;
+ box-shadow: none;
+ box-sizing: border-box; }
+/* Removes awkward default styles on some inputs for iOS */
+input[type="email"],
+input[type="number"],
+input[type="search"],
+input[type="text"],
+input[type="tel"],
+input[type="url"],
+input[type="password"],
+textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none; }
+textarea {
+ min-height: 65px;
+ padding-top: 6px;
+ padding-bottom: 6px; }
+input[type="email"]:focus,
+input[type="number"]:focus,
+input[type="search"]:focus,
+input[type="text"]:focus,
+input[type="tel"]:focus,
+input[type="url"]:focus,
+input[type="password"]:focus,
+textarea:focus,
+select:focus {
+ border: 1px solid #33C3F0;
+ outline: 0; }
+label,
+legend {
+ display: block;
+ margin-bottom: .5rem;
+ font-weight: 600; }
+fieldset {
+ padding: 0;
+ border-width: 0; }
+input[type="checkbox"],
+input[type="radio"] {
+ display: inline; }
+label > .label-body {
+ display: inline-block;
+ margin-left: .5rem;
+ font-weight: normal; }
+
+
+/* Lists
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+ul {
+ list-style: circle inside; }
+ol {
+ list-style: decimal inside; }
+ol, ul {
+ padding-left: 0;
+ margin-top: 0; }
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin: 1.5rem 0 1.5rem 3rem;
+ font-size: 90%; }
+li {
+ margin-bottom: 1rem; }
+
+
+/* Code
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+code {
+ padding: .2rem .5rem;
+ margin: 0 .2rem;
+ font-size: 90%;
+ white-space: nowrap;
+ background: #F1F1F1;
+ border: 1px solid #E1E1E1;
+ border-radius: 4px; }
+pre > code {
+ display: block;
+ padding: 1rem 1.5rem;
+ white-space: pre; }
+
+
+/* Tables
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+th,
+td {
+ padding: 12px 15px;
+ text-align: left;
+ border-bottom: 1px solid #E1E1E1; }
+th:first-child,
+td:first-child {
+ padding-left: 0; }
+th:last-child,
+td:last-child {
+ padding-right: 0; }
+
+
+/* Spacing
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+button,
+.button {
+ margin-bottom: 1rem; }
+input,
+textarea,
+select,
+fieldset {
+ margin-bottom: 1.5rem; }
+pre,
+blockquote,
+dl,
+figure,
+table,
+p,
+ul,
+ol,
+form {
+ margin-bottom: 2.5rem; }
+
+
+/* Utilities
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+.u-full-width {
+ width: 100%;
+ box-sizing: border-box; }
+.u-max-full-width {
+ max-width: 100%;
+ box-sizing: border-box; }
+.u-pull-right {
+ float: right; }
+.u-pull-left {
+ float: left; }
+
+
+/* Misc
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+hr {
+ margin-top: 3rem;
+ margin-bottom: 3.5rem;
+ border-width: 0;
+ border-top: 1px solid #E1E1E1; }
+
+
+/* Clearing
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+
+/* Self Clearing Goodness */
+.container:after,
+.row:after,
+.u-cf {
+ content: "";
+ display: table;
+ clear: both; }
+
+
+/* Media Queries
+–––––––––––––––––––––––––––––––––––––––––––––––––– */
+/*
+Note: The best way to structure the use of media queries is to create the queries
+near the relevant code. For example, if you wanted to change the styles for buttons
+on small devices, paste the mobile query code up in the buttons section and style it
+there.
+*/
+
+
+/* Larger than mobile */
+@media (min-width: 400px) {}
+
+/* Larger than phablet (also point when grid becomes active) */
+@media (min-width: 550px) {}
+
+/* Larger than tablet */
+@media (min-width: 750px) {}
+
+/* Larger than desktop */
+@media (min-width: 1000px) {}
+
+/* Larger than Desktop HD */
+@media (min-width: 1200px) {}
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/html/images/favicon.png b/exercises/devops/solutions/deploy_to_kubernetes/html/images/favicon.png
new file mode 100644
index 0000000..7a3c81c
Binary files /dev/null and b/exercises/devops/solutions/deploy_to_kubernetes/html/images/favicon.png differ
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/html/index.html b/exercises/devops/solutions/deploy_to_kubernetes/html/index.html
new file mode 100644
index 0000000..7a51873
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/html/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ Hello World :)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hello World :)
+
+
+
+
+
+
+
diff --git a/exercises/devops/solutions/deploy_to_kubernetes/inventory b/exercises/devops/solutions/deploy_to_kubernetes/inventory
new file mode 100644
index 0000000..077c7af
--- /dev/null
+++ b/exercises/devops/solutions/deploy_to_kubernetes/inventory
@@ -0,0 +1,2 @@
+[kubernetes]
+x.x.x.x
diff --git a/exercises/jenkins/jobs_101.md b/exercises/jenkins/jobs_101.md
new file mode 100644
index 0000000..7cc0399
--- /dev/null
+++ b/exercises/jenkins/jobs_101.md
@@ -0,0 +1,4 @@
+## Jobs 101
+
+1. Create a new job/pipeline
+2. Make sure every time the job is triggered it prints the current date
diff --git a/exercises/openshift/projects_101.md b/exercises/openshift/projects_101.md
new file mode 100644
index 0000000..3ccbf9f
--- /dev/null
+++ b/exercises/openshift/projects_101.md
@@ -0,0 +1,8 @@
+## OpenShift - Projects 101
+
+In a newly deployed cluster (preferably) perform and answer the following instructions and questions, using CLI only
+
+1. Login to the OpenShift cluster
+2. List all the projects
+3. Create a new project called 'neverland'
+4. Check the overview status of the current project
diff --git a/exercises/openshift/solutions/projects_101.md b/exercises/openshift/solutions/projects_101.md
new file mode 100644
index 0000000..e7e2265
--- /dev/null
+++ b/exercises/openshift/solutions/projects_101.md
@@ -0,0 +1,6 @@
+## Projects 101 - Solution
+
+1. Login to the OpenShift cluster -> `oc login -u YOUR_USER -p YOUR_PASSWORD_OR_TOKEN`
+2. List all the projects -> `oc get projects`(The output should be empty in a newly created cluster)
+3. Create a new project called 'neverland' -> `oc new-project neverland`
+4. Check the overview status of the current project -> `oc status`
diff --git a/exercises/python/advanced_data_types.md b/exercises/python/advanced_data_types.md
new file mode 100644
index 0000000..40a4aa4
--- /dev/null
+++ b/exercises/python/advanced_data_types.md
@@ -0,0 +1,9 @@
+## (Advanced) Identify the data type
+
+For each of the following, identify what is the data type of the result variable
+
+1. a = {'a', 'b', 'c'}
+2. b = {'1': '2'}
+4. c = ([1, 2, 3])
+4. d = (1, 2, 3)
+4. e = True+True
diff --git a/exercises/python/compress_string.md b/exercises/python/compress_string.md
new file mode 100644
index 0000000..20bbad1
--- /dev/null
+++ b/exercises/python/compress_string.md
@@ -0,0 +1,8 @@
+## Compress String
+
+1. Write a function that gets a string and compresses it
+ - 'aaaabbccc' -> 'a4b2c3'
+ - 'abbbc' -> 'a1b3c1'
+2. Write a function that decompresses a given string
+ - 'a4b2c3' -> 'aaaabbccc'
+ - 'a1b3c1' -> 'abbbc'
diff --git a/exercises/python/data_types.md b/exercises/python/data_types.md
new file mode 100644
index 0000000..978f372
--- /dev/null
+++ b/exercises/python/data_types.md
@@ -0,0 +1,12 @@
+## Data Types
+
+For each of the following, identify what is the data type of the result variable
+
+1. a = [1, 2, 3, 4, 5]
+2. b = "Hello, is it me you looking for?"
+3. e = 100
+4. f = '100'
+5. i = 0.100
+6. i = True
+
+Bonus question: how to find out in Python what is the data type of certain variable?
diff --git a/exercises/python/reverse_string.md b/exercises/python/reverse_string.md
new file mode 100644
index 0000000..7e7ecc1
--- /dev/null
+++ b/exercises/python/reverse_string.md
@@ -0,0 +1,3 @@
+## Reverse a String
+
+Write a code that reverses a string
diff --git a/exercises/python/solutions/advanced_data_types_solution.md b/exercises/python/solutions/advanced_data_types_solution.md
new file mode 100644
index 0000000..068b56d
--- /dev/null
+++ b/exercises/python/solutions/advanced_data_types_solution.md
@@ -0,0 +1,9 @@
+## (Advanced) Identify the data type
+
+For each of the following, identify what is the data type of the result variable
+
+1. a = {'a', 'b', 'c'} -> set
+2. b = {'1': '2'} -> dict
+4. c = ([1, 2, 3]) -> list
+4. d = (1, 2, 3) -> tuple
+4. e = True+True -> int
diff --git a/exercises/python/solutions/data_types_solution.md b/exercises/python/solutions/data_types_solution.md
new file mode 100644
index 0000000..074f27f
--- /dev/null
+++ b/exercises/python/solutions/data_types_solution.md
@@ -0,0 +1,12 @@
+## Data Types - Solution
+
+1. a = [1, 2, 3, 4, 5] -> list
+2. b = "Hello, is it me you looking for?" -> string
+3. e = 100 -> int
+4. f = '100' -> string
+5. i = 0.100 -> float
+6. i = True -> bool
+
+### Bonus question - Answer
+
+`type(...)`
diff --git a/exercises/python/solutions/reverse_string.md b/exercises/python/solutions/reverse_string.md
new file mode 100644
index 0000000..9ea6874
--- /dev/null
+++ b/exercises/python/solutions/reverse_string.md
@@ -0,0 +1,16 @@
+## Reverse a String - Solution
+
+```
+my_string[::-1]
+```
+
+A more visual way is:
+Careful: this is very slow
+
+```
+def reverse_string(string):
+ temp = ""
+ for char in string:
+ temp = char + temp
+ return temp
+```
diff --git a/exercises/sql/improve_query.md b/exercises/sql/improve_query.md
new file mode 100644
index 0000000..0891a5c
--- /dev/null
+++ b/exercises/sql/improve_query.md
@@ -0,0 +1,10 @@
+## Comparisons vs. Functions
+
+1. Improve the following query
+
+```
+SELECT count(*)
+FROM shawarma_purchases
+WHERE
+ YEAR(purchased_at) == '2017'
+```
diff --git a/exercises/sql/solutions/improve_query.md b/exercises/sql/solutions/improve_query.md
new file mode 100644
index 0000000..1f3eaaa
--- /dev/null
+++ b/exercises/sql/solutions/improve_query.md
@@ -0,0 +1,9 @@
+## Comparisons vs. Functions - Solution
+
+```
+SELECT count(*)
+FROM shawarma_purchases
+WHERE
+ purchased_at >= '2017-01-01' AND
+ purchased_at <= '2017-31-12'
+```