Saturday, September 2, 2017

Conditions and iterations in chef-ruby

Conditions and iterations:

Whenever you write :install (it is something termed as symbol with Ruby).
(only Ruby has the concept of symbol).

With strings,what is the problem, the memory management is the complicated one.
(with ruby,we can reduce that issue).

Note:
Ruby maintain,there own cache.
Ruby do the management of dynamic memory allocation.
When we use this :install instead of this “install”

Value wise,there is no difference,wherever it is suggested,but the storage wise and alogarithm wise,symbol is better

Note:
Problem with the symbol is,symbol once assigned to a variable cannot be changed.
(memory allocation,whatever you give,it will try to reuse it),which does not happened.

Example:

I have created a symbol called the :install (representation of symbol in ruby),now we have used the variable and now we want to change its value.still no problem we can change it,but the install memory allocation/location,which has been created,it will try to see the,if any other ruby program asking for it.(it will try to give from cache,rather than creating).

In most of the cases,we will be writing:

Action  :install
Action  :start
(these everything,made as a symbol and these are reused).
(There wil not be  a new memory always).

Note:
If your looking for values,that is the rubies way of doing it.
(ruby has a efficient way of looking at things).

But,from the development perspective of the chef,it is no different than string,creating that in the double quotes or the single quotes.

Value wise,there is no difference.

Symbol is nothing but a string.

Whenever you write programming,you write steps of instructions:
(it will execute in the order you have written it).

There are situations,you want to execute,some in one case and some in other case.

For example,
In case of banking withdrawal.
Depositing the amount from one account to another account.


While writing configuration management,there will be many scenarios.

We should have a sequential flow and at the same time,it should know what to execute and what to skip.

Ruby scenario:

Goal : apache webserver:

Package  ‘apache2’  do
    Action  :install
End

Package ‘httpd’ do
   Action :install
End

(is there ,any case,where we need to execute both the statements).
You will execute either one of them,how to control it?

For example:
If you take the facter command (the complete information is assigned to a variable) = facts.
And from there we will access the data through array representation.


To make,this kind of decisions,we would be using the conditions:

There are two kinds of conditions broadly:
That is if and other one Is unless.

The basic syntax of  if is :
In if you write some ruby expression,if return true or false.

If  <ruby expression>
End

You written,in this one code.

If  <ruby expression>
     <code>
End
Whatever written will be executed,if your expression returns true.

Unless <ruby expression>
     <code>
End
Whatever written will be executed,if your expression returns false.

Unless  = notif  or ifnot

If node = Ubuntu
Then execute this.
If node is not equal to Ubuntu (unless)
Then execute this

Basically,when we use if or unless,where we have the scenario always only one condition right.

Let us example,that I have to do the separate installation for Ubuntu 14.04,Ubuntu 16 and Ubuntu 12.

I have three conditions.
I have to make decision,out of three.
And that may come,another operating system,either of this three.

There are four conditions,which I need to write:

One is for Ubuntu 12
Another one is Ubuntu 14,16 and any other thing,we are not going to execute this.

In this case,your building something called ladders.

Lets us assume,operating system in  a variable called as OS.

If osname== “ubuntu12”
       <code1>
elsif  osname == “ubuntu14” (whenever you writing elseif in ruby,you wont see ‘e’ in ruby).
(incase of python,it is elif).
       <code2>
elsif osname == “ubuntu16”
       <code3>
(Purpose:if you have more than two conditions,we have to go for elsif).
(if you have only two conditions If and unless).
end

Better ways of doing this,write a case statements: (very rarely we use this).
Case statement is a switch statement in `C`.
In `c` it is switch and variable.

Array and hashs:

What is an Array?
Array is datatype,which is capable of holding multiple data.
(In other languages:multiple homogeneous data,belonging to the same datatype).

In the case of ruby,that is not the case:
It Is multiple objects (that may be numbers,strings and whatever may be).

Whenever you look at the data in an  array,
Like if we have four positions in an array:
Myarray (0) gives the first position.
(if I want a specify item,we will be using that).

What if ,if I want to do for every package,I want to install?
Package_name  = [“apache”,”tomcat”,”tree”]
I have been asked to install these three packages.

Today,the value of this is 3 and tomorrow may be 4,size may increase.
So,I cannot write multiple package statements.

Basically,we will use the ruby block of statements.

Package_names.each  do  |here we will define the variable name|
In the first iteration,the value will be `apache`
(mypackname during the first iteration will be apache).
During the second iterations,the value will be tomcat.
During the third iteration,the value will be tree.
(we will use this syntax,to write the code block).

(it will iterate and in every iterate,it will give you the value).
(it will start from 0th position).

   Package_names.each  do  |my packname|
           Action   :install
   End
End
(I have written,which executes mypackname thrice).
(nothing but a simple  `For loop`).
You also have a `For loop` in ruby

For example,if it is an Array wonderful.


Package_details=
{
   name =>  “apache2”,
   version  =>  “14”
    }

if you want to iterate,through a hash.

Package_details.each  do  | k,v |
    Echo   k,v
End

(Actually,we can iterate through hashes also).
(it is just indexing by a position).


Note:
(here,we are getting two variable,incase of array,we have one).
Name will be part of key
Value will be part of v.
(what are the possible values,you get in every iteration,you get  a key and value).


Chef generate cookbook  < name of the cookbook>

Chef generate cookbook   variables_demo
(it will create the cookbook,with basic boilerplate).

Metadata.rb
(this is the place where,you write the details about the cookbook).

(We know that,if you use the resource package,we can install the packages depending upon the system).
(what will be installed,in that we will give as an variable).

Basically,the variable name initially is:

Package_to_be_installed = “tomcat”

Package ‘Package_to_be_installed  do
     Action :install
End


Problem:I have to change this code,everytime,to change the variable value.
(I want variable value to be changing,depending upon the flavor of the operating system)
(for example,the value for the ubutnu to be tomcat7 and for the centos it will be tomcat,depending upon the os the variable has to be changing,what is the solution for that?)

Incase of redhat machines
(I want to basically installed httpd).
To get that,if we use the:

Node [‘os’]  --à this will give us the hash.what the `facter os` does.

Let us execute the same command in the linux machine and see what happens:
(let us find out,what is the node statement,we have to write,to find out,whether it is the Ubuntu/centos or any other kind of operating system).

Whatever the command ‘facter’ we are using in the windows and it is different in the linux virtual machines.

Don’t assign the structure,what is written in the windows,always  it is suggested to execute facter,atleast the os where you want to execute.

Example,if I want to execute on the redhat.
(from redhat and Ubuntu,you don’t see any structural changes).
(but from windows to linux,you see the structural changes and next to mac,there will be some changes).

Example:when you type facter in the linux machines,what happends?

Ubuntu@ip :-$  sudo –i
root@ip :-$  facter
The program ‘facter’ is currently not installed.you can install it by
Apt-get install facter
(this is the problem,because,we did not installed chefdk).

Example:

  Node [kernel] [name]

Chef server > goto specific node  >  attributes > kernel > name:linux
(this is the multi structured).
(if one to access,other things ,I need to use the
  node [structure]
(node [structure] is technically called is  node[object]).

Which is every important,during the chef.

Incase,even in  the ansible.
We have a section called the gatherfacts.

In every,configuration management tool,server will try to maintain.details about your node.
(every tool,will have its own way of looking at it).

Incase of chef,we called it as Node object

Note:
Node object contains details of,all of the possible.details about the system.

It will also,tells about the network,what are the network interfaces we have:
Eth0 basically and what is io?
And what different values,which you have  and possible address which you have.

Note:
Everything,it will try to maintain:

(this details,will be given by your server,by a command line utility called the facter).

When you install chefdk,facter will be in working,but that is not the,when you use the knife).


We have to write something,which I have to be worked,based out of family:
(That is the debian family or redhat family).

So,you will be using the platform_family


In my code,I will be writing/adding:

Previous code:
Node [`os`]

Package_to_be_installed = “tomcat”

Package ‘Package_to_be_installed  do
     Action :install
End

Modified code(according to the family,it has to install the packages):

Node [`os`]

If node[‘platform’] = =  “Ubuntu”
Package_to_be_installed = “apache2”
Elsif node[‘platform’] = = “redhat”
Package_to_be_installed = “httpd”
End

Note:
(the problem which I said,still exists,because,this is a variable and the value of it,your writing it,very much near to the code and to read this value,what has to be the decision.decision is taken where you have the code,straightly and it is dependent where your code is).
(Anytime,your changing here,is as good as code).

For example:
I tried to install the tomcat,changing apache to tomcat.everytime,what I am trying,I am trying to change the file,where the code is present.
(so,it Is as good as code change right).

Note:
We should,look at the options,where this kind,variable assignment where this kind of variable assignment,should not present in the recipes,there should be present somewhere.

And our recipes,should try to use that,rather than,basically,defining the values over there.

Steps,how we have written the packages,using the variables in different styles:

First trial:
First thing,what we have written,we have written a logic for installation.we used package.

Second trial:
After that,what is my responsilibilty to make it,good,what I did is,I made in to a variable.
Variables has two ways of possibilities,I have written the  `if`  statement.

The problem,with the above two approaches:
We have data and the code at the same place.
Which is always,does not seems to be good.

Our code,should access the data,always from the same place.

So,basically,whenever I changed the data and execute the code again and again.
It requires execution and no compilation required.

So,it will work,even with different values.
(this is different kind of variable value assignments).

Don’t keep code and data in same place.(whenever your coding,there should be independent of eachother).

Thereshould be a places,where we should write,for code and data separately.

This thought in chef,gave a new concept called attribute.

Attribute exactly solves this problem.

What is an attribute?
The place,where you define your variables.
Rather than,using and writing like this,you would write this parts,where you have the variable and defintions in other folder/in some other file.

For generating the attributes:
>>>>>>>>>>>>>>>>>>>>>>> chef generate attribute  .  default
(what happens,there is a new folder,which is called attributes and a new file is generated is called the default file).

Any variables,will be moving to this.

(this attributes,we can set it,independent of the code).  >>>>> this is the first step.

First thing is,write a variable in your code itself and second try it,whether you can access this from the external file or not.

You might not able to,some times it is a intermediate variable/sometimes we can set this value from the external world.

For example:
The return part,which comes out of the first part,if you want to use that as a attribute,you cannot able to do that.

But the value,which you set to the package,you can able to do that.

For writing values to that attribute:

There is an syntax,which we need to follow:

Attribute is a place where,where we can set all our variable,which is related to the cookbook.
Attribute is a place where,where we define the variables,which acts as a variables in the cookbook.
-------------------------------------------------------------------------------------------------------------
Default.rb  (attributes)

Generally the first thing,you write in most of the  cases is the cookbookname.

Description:
[ Default [‘cookbookname] [‘name of the variable’].value
(packagename:why do we want to write a variable name,because,which can hold the packages name)
[(packagename à this is going to be our variable,to this,we will set our value).]


Default [‘variables_demo’] [‘packagename’] =”apache2”
Default [‘variables_demo’] [‘servicename’] =”apache2”

Note:
Generally,we wont define two variables.

#Cookbookname:: variables_demo
#recipe ::Default.

***Whenever you want to access any attribute,we have to write  node []

Package node [‘variables_demo’] [packagename] do
        Action  :install
End
Service node [‘variables_demo’] [servicename] do
        Action  :start
End
[**I want to start the service
generally the service name and package name will be equal  in 99% of cases.]

Node > attributes >> consists of two things,one the attributes define by you and second is the attributes fetched by the facter.

Basically,you can try to define attributes also. (Edit node attributes) and wait for the next convergence.

Attributes contain,what we write in the default.rb and it also contain the,whatever the facter writtens,
[facter variables + whatever we written in the attribute files] >>> (combined) >> sent back to the chef server.
Whenever we speak of attributes,there are two things:

1)fetched from the facter.
2)the attributes,defined in cookbooks.

(we can see these all the details in the node > attributes).

One layer deeper and see what happens:

****Chef is a push model

During converegence time:
chef server    <<<< ========  chef node
(chef node,will basically question(communicate) with the chef-server,is there anything new to do?)

Description:
For example,this is the cookbook,we have changed and we have uploaded to the server,the server,yes there is a new cookbook called XXX and we have to apply that and that also will be added to the run_list.basically as a result of that,that cookbook,it will be executed over there.
And that contains our attributes and the chef node have a facter,so the facter will be executed,and attributes are read and those two things are combined and there is some alogarithm that executes and chef server returns back,something called as node objects,exactly that node objects,we are trying to access is called node[].

Node [platform] right,that means your trying to access the node object.
(that is nothing but the,variables defined you + variables/facts of our node/operating system/wherever your running your stuff).

For example:

If you want to execute the script,that is free memory above 1GB.
(you have the info from the facts/node object which contains all these information).


There are 16 precendence levels,that we need to understand.
Because the variables,whatever we defined in the attributes section,with the same  I can define in different places,

Note:
While defining,you will define as default[]  (that is in the attributes folder and in the default file).
While your using that,you defined as node[] (that is in the recipes foler and for the default.rb file).

Note:
Default [‘variables_demo’] [‘packagename’] =”apache2”
If you want to install tomcat instead of apache2,just change the value from apache2 to tomcat,here your not touching anything of the code.

I can override,these values from multiple places.
This makes it simple,my code is not effected,with the variable changes.

If you understand the attributes and attributes precendences,we can easily understand the roles and environments and we have the section called as databags.


writing recipes (for this you require resources).

No comments:

Post a Comment