
\chapter{Praktická část}\label{subsec:PraktickáČást}

V této kapitole jsou popsány postupy pro implementaci Wordpressu pomocí vybraných nástrojů konfiguračního managementu.

\section{Vytvoření prostředí pro práci}\label{subsec:VytvořeníProstředíProPráci}
První krok je vytvoření routeru, sítě a strojů v cloudovém prostředí OpenStack. Vytvořený router je spojením mezi internetem a vnitřní sítí, ve které jsou stroje. Na těchto strojích jsou jednotlivé nástroje konfiguračního managementu a také instance Wordpressu. Díky tomuto routeru se dá ovládat jednotlivé stroje přes internet, a proto není potřeba být ve stejné síti jako je cloud.
\\[12pt]Obrázek použitých strojů z prostředí OpenStack:
\begin{figure}[h!]
    \begin{centering}
        \includegraphics[width=0.8\textwidth]{img/nodes}
    \par\end{centering}
    \caption{OpenStack – použité stroje}
\end{figure}

\section{Informace o Implementaci}\label{subsec:InformaceOImplementaci}
Po zpracování prostředí je na čase implementovat Wordpress a WP-CLI. Tyto části jsou instalovány na jednotlivé stroje pomocí různých nástrojů konfiguračního managementu. Pro instalaci Wordpressu a aktualizace se využívá hlavně nástroj WP-CLI. Pokud ale nebude možné tento nástroj nainstalovat, tak bude instalace dokončena pomocí jiných součástí, jako je Git nebo Linuxové příkazy.

\subsection{Wordpress}\label{subsec:ImplementaceWordpress}
Implementace Wordpressu se skládá z kopírování základních souborů na server a vytvoření databáze. Dalším krokem je instalace Wordpressu, která se dá provést pomocí přístupu přes prohlížeč, kde se nastavují přihlašovací údaje k databázi a poté k Wordpressu jako takovému. Tento krok je automatizován, aby stránky fungovaly okamžitě po nasazení. Proto je potřeba vytvořit konfigurační soubor (wp-config.php), který se nahraje do šložky s Wordpressem. Následující krok je automatizace instalace databázových tabulek a jejímu naplenění pomocí základních (defaultních) hodnot. Posledním krokem v nasazování je instalace vybraných rozšíření, šablon a zpracování aktualizace celého systému.
\\[12pt]Proto je postup práce takový:
\begin{itemize}
\item Vytvoření složek a nakopírování souborů Wordpressu.
\item Nahrání upraveného souboru wp-config.
\item Vytvoření databáze a vložení základních dat.
\item Instalace rozšíření a témat + aktualizace.
\end{itemize}

\section{Implementace pomocí Salt}\label{subsec:ImplementacePomocíSalt}
Salt funguje na bázi master/minion, proto je potřeba na hlavním stroji vynutit součásti, jak pro ovládání, tak i pro ovládané stroje. Některé další součásti budou Git, Linux, OpenSSH a reclass. A poslední vynucované části jsou formule, které zaručí kompletní nastavení jednotlivých součástí. Veškeré konfigurační soubory jsou zapsány v jazyce Yaml.
\pagebreak
\\[12pt]Příklad nastavení součástí na masteru:
\begin{lstlisting}[caption=Master součásti (Salt)]
classes:
- system.git.client
- system.linux.system.single
- system.openssh.client.cluster.cloudlab
- system.openssh.server.team.tcpcloud
- system.salt.minion.master
- system.salt.master.single
- system.salt.master.formula.linux
- system.salt.master.formula.saltstack
- system.salt.master.formula.wordpress
- system.reclass.storage.salt
- system.reclass.storage.system.webapp_stg
\end{lstlisting}
Detailní nastavení dalších tří strojů je pomocí \verb|webapp_stg.yml|, ve kterém jsou definované součásti pro každý stroj. K součástem se také mohou přidat jednotlivé parametry, které jsou potřebné k jejich správnému fungování.
\\[12pt]Parametry na masteru:
\begin{lstlisting}[caption=Master parametry (Salt)]
parameters:
  _param:
    reclass_data_repository: git@repo1.robotice.cz:reclass-models/dels-salt-model.git
    reclass_data_revision: master
    reclass_config_master: 192.168.11.100
    salt_master_host: 127.0.0.1
    salt_master_environment_name: dev
    salt_master_environment_repository: git@repo1.robotice.cz:saltstack-formulas
    salt_master_environment_revision: develop
\end{lstlisting}
Tyto parametry nastavují url odkaz do Gitlabu, ze kterého má master stáhnout reclass a Salt. K tomuto stahování se také uvádí verze (revision) jakou má Git stahovat. U reclassu je důležité nastavit ip adresu hlavního stroje, tato adresa je nastavena na ovládaných strojích, aby byla možná komunikace strojů. Poslední nastavení je verze pro Salt a v jakém prostředí se pracuje, jestli ve vývojovém nebo produkčním.

Po nastavení mastera se přejde k vytvoření konfigurace pro Salt miniona, ve které se vynucuje Linux, openssh a Wordpress formule.
\\[12pt]Nastavení součástí jednoho miniona:
\begin{lstlisting}[caption=Minion součásti (Salt)]
node:
  wordpress_web_salt_stg:
    name: web01
    domain: wordpress.dls.vpc.cloudlab.cz
    classes:
    - system.linux.system.single
    - system.openssh.client.cluster.cloudlab
    - system.openssh.server.team.tcpcloud
    - system.wordpress.server.multi
    - system.wordpress.server.app.devel
    params:
      salt_master_host: ${_param:reclass_config_master}
      apache_wordpress_devel_host: wordpress-salt.robotice.cz
      mysql_wordpress_devel_password: password
\end{lstlisting}
V této části se nastavují jak součásti, tak nutné parametry pro správnou funkčnost a komunikaci mezi ovládaným a ovládajícím strojem. Jeden z těchto parametrů musí být IP adresa mastera, na kterou ovládaný stroj zasílá informace. Při zpracování webových stránek je také důležité, aby byly přístupné z internetu pomocí url adresy, proto je zde i toto nastavení.

Po těchto nastaveních se může přejít k vytvoření Wordpress formule, díky které se instance Wordpressu instaluje na ovládaný stroj. Instalace jako taková se povede příkazem na serveru \verb|salt ‘web01*’ state.sls wordpress|. Tento příkaz říká Saltu, aby aktualizoval formuli Wordpress na stroji se jménem začínajícím web01.

\subsection{Vytvoření souborů Wordpressu}\label{subsec:VytvořeníSouborůWordpressu}
Před vytvořením souborů Wordpressu se musí vytvořit složka, ve které budou soubory umístěny. K tomu se využije Sakt funkce file.directory, která zajišťuje, že složka existuje a má správně nastavená přístupová práva. Pokud neexistuje, tak ji vytvoří.
\\[12pt]Vytvoření složky pro soubory Wordpressu:
\begin{lstlisting}[caption=Vytvoření složky WP]
/srv/wordpress/sites/{{ app_name }}:
  file.directory:
  - user: www-data
  - group: www-data
  - mode: 770
  - makedirs: true
\end{lstlisting}
Parametr \verb|app_name| je nastaven v konfiguračním yml souboru a nejčastěji má stejnou hodnotu jako url odkaz stránek, které se vytváří, ale není to nutné.\cite{SaltFile}

Následujícím krokem je stažení Wordpress souborů do nově vytvořené složky. K tomuto úkolu se využije nástroj Git, který stáhne všechny soubory a umístí je do vytvořené složky.
\begin{lstlisting}[caption=Stažení WP]
wordpress_{{ app_name }}_git:
  git.latest:
  - name: {{ server.git_source }}
  - rev: {{ app.version }}-branch
  - target: /srv/wordpress/sites/{{ app_name }}/root
  - user: www-data
  - require:
    - pkg: git_packages
\end{lstlisting}
Paramter \verb|app_name| je v tomto případě stejný jako v předchozím případě. Do části name se vkládá zdrojová url adresa, ze které Git stahuje soubory Wordpressu. Díky rev (revision) se můžou stahovat různé verze Wordpressu. Je důležité aby se tato funkce spuštěla pod uživatelem www-data, který je vlastníkem vytvořené složky. Je to z důvodu, aby se zajistilo, že má práva pro zápis do této složky. Pomocí tohoto uživatele se také instalují rozšíření a aktualizují součásti Wordpressu.

\subsection{Úprava souboru wp-config}\label{subsec:ÚpravaSouboruWp-config}
Soubor wp-config je před nahráním do určené složky upraven podle informací, které jsou uvedeny v yml soubu. Díky těmto úpravám je možné vytvářet rozdílné databáze a různé stránky fungující na systému Wordpress.

S využitím příkazu file.managed, se přesune tento soubor do složky Wordpressu s využitím nástroje Git. Tento příkaz tedy nejdříve soubor upraví podle zadaných informací a poté ho přesune.
\\[12pt]Přesun souboru wp-config:
\begin{lstlisting}[caption=Přesun souboru wp-config]
/srv/wordpress/sites/{{ app_name }}/root/wp-config.php:
  file.managed:
  - source: salt://wordpress/files/wp-config.php
  - template: jinja
  - mode: 644
  - require:
    - git: wordpress_{{ app_name }}_git
  - defaults:
    app_name: "{{ app_name }}"
\end{lstlisting}
Díky možnosti template jsou do tohoto souboru nastavena data z yml souboru. Poté je volána součást Git jako required (vyžadovaná) součást pro přesun souboru.

\subsection{Instalace nástroje WP-CLI}\label{subsec:InstalaceNástrojeWP-CLI}
Před dokončením instalace Wordpressu a jeho dalších součástí je potřeba nainstalovat WP-CLI, protože s jeho pomocí se vytváří potřebná základní data a vkládají se do databáze.

Nejdříve se nakopíruje soubor, ve kterém je zapsán instalační script pro instalaci dokončování příkazů po WP-CLI. Kód pro tento úkol je skoro stejný jako pro přesun souboru wp-config. Jediný rozdíl je v použitých jménech a složce. Tento kód využívá složku pro dočasné soubory, aby se instalační soubor po provedení smazal.

Hlavním krokem této části je instalace WP-CLI, která je provedena pomocí standardního scriptu pro Linux. Tento script stáhne soubor s WP-CLI a nainstaluje ho s nastavenými právy. Následující část scriptu spustí instalaci pro dokončování příkazů WP-CLI.
\\[12pt]Spuštění instalace WP-CLI pomocí cmd:
\begin{lstlisting}[caption=Spouštění instalace WP-CLI]
install_wpcli:
  cmd.script:
    - name: wpcli-install
    - source: salt://wordpress/files/wpcli-install.sh
    - cwd: /
    - user: root
    - require:
      - git: wordpress_{{ app_name }}_git
    - unless: wp cli version --allow-root
\end{lstlisting}
Pomocí příkazu cmd.script se spustí tento instalační script a není tak potřeba ho kopírovat na ovládaný stroj. Kód probíhá pod uživatelem root, protože potřebuje práva na zápis do složek do kterých uživatel www-data nemá přístup. Možnost unless zajišťuje, aby se WP-CLI neinstalovalo opakovaně, pokud již existuje.
\\[12pt]Instalační script WP-CLI:
\begin{lstlisting}[caption=Instalační script WP-CLI]
#!/bin/bash
curl -O https://raw.githubusercontent.com/wp-cli/builds/
         gh-pages/phar/wp-cli.phar

chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

chmod +x /tmp/wpcli-tab.sh
source /tmp/wpcli-tab.sh
\end{lstlisting}
Nejdříve se musí určit, že se jedná o Linuxový bash script. Poté se s pomocí curl stáhne soubor wp-cli a dalšími řádky zajistí, že se WP-CLI může spustit a přesune jej do složky ve které jsou přítomny další funkce Linuxu. Soubor se díky tomu i přejmenuje na wp, aby se nemuselo pokaždé psát wp-cli.phar místo wp. Poslední řádky tohoto scriptu umožňí spuštění instalačního scriptu pro dokončování příkazů.

\subsection{Instalace databáze}\label{subsec:InstalaceDatabáze}
Při implementaci databáze jsou dva postupy, které jsou zpracovány. Prvním je s podporou WP-CLI, protože umí vytvořit tabulky v databázi přesně podle verze Wordpressu. Tento postup je vhodnější, protože funguje v propojení s danou verzí Wordpressu.
\\[12pt]Instalace databáze a dat pomocí WP-CLI:
\begin{lstlisting}[caption=Instalace databáze s WP-CLI]
{%- if salt['cmd.retcode']('wp core is-installed --path="'+web_path+'" --allow-root') == 1 %}
wp_install:
  cmd.run:
    - name: wp core install --url='{{ app.core_install.url }}' --title='{{ app.core_install.title }}' --admin_user='{{ app.core_install.admin_user }}' --admin_password='{{ app.core_install.admin_password }}' --admin_email='{{ app.core_install.admin_email }}'
    - cwd: {{ web_path }}
    - user: www-data
{%- endif %}
\end{lstlisting}
Nejdříve se musí zabezpečit, aby se databáze neinstalovala pokaždé, protože by se tabulky pokaždé přepisovaly. Proto funkce if zjišťuje, jestli jsou tabulky nainstalované pomocí příkazu WP-CLI a rozhoduje, zda nainstalovat databázi nebo ne. Pokud tedy tabulky neexitují, tak se spustí příkaz wp core install, který je vytvoří. Tento příkaz využívá instalační informace z yml souboru, které by se jinak musely zadávat při přístupu z webového prohlížeče.

Druhá možnost je instalace datábáze bez WP-CLI. Jde o instalaci pomocí Linuxového příkazu, který nahraje základní data ze souboru sql. Tento soubor obsahuje základní Wordpress databázi z verze 4.1, takže pokud by se použil na nižsí verzi, je možné že by Wordpress nefungoval správně. Je náročné tento soubor správně upravit, aby nepůsobil problémy. Wordpress sice disponuje možností aktualizace databáze, ale ne vždy toto řešení pomůže.

Nejdříve se pomocí Gitu zkopíruje soubor sql na ovládaný stroj, proto se znovu využije funkce file.managed. Kód je znovu téměř identický jako v případě wp-config. Když je tento soubor přesunut, je poté využit pomocí Linuxového příkazu pro přesun do MySQL databáze. To zpracuje kód ze souboru a vytvoří tabulky s daty.
\\[12pt]Instalace databáze a dat pomocí příkazu mysql:
\begin{lstlisting}[caption=Instalace DB bez WP-CLI]
create_db:
  cmd.run:
    - name: mysql -u {{ app.database.user }} -p{{ app.database.password }} < /tmp/init.mysql
    - require:
      - service: mysql
      - file: /tmp/init.mysql
\end{lstlisting}
Po těchto krocích je nainstalovaný základní Wordpress a připravený k použití.

\subsection{Instalace rozšíření, šablon a aktualizací}
Instalování rozšíření a jejich aktualizace je velice podobná záležitost, kde jediná změna je ze slova install na update. Aktualizace jako taková je zpracována pro všechny součásti Wordpressu i jeho jádro.

Stažení a instalace rozšíření nebo šablon probíhá cyklem, aby se nainstalovaly všechny součásti a ne jenom jedna. Veškeré tyto kódy jsou uzavřeny v tomto cyklu a jsou kontrolovány podmínkami, aby proběhla pouze jedna akce pro každé rozšíření.
\\[12pt]Obalení cyklem for:
\begin{lstlisting}[caption=For pro rozšíření]
{%- for plugin_name, plugin in app.plugin.iteritems() %}
% Kód pro Aktualizaci / Instalaci %
{%- endfor %}
\end{lstlisting}
Díky tomuto cyklu je také možné se dostat k nastaveným informacím pro každé rozšíření, jako je jeho verze a způsob instalace. Tyto informace jsou použity v následujících kódech pro kontroly instalace nebo aktualizace.

Instalování rozšíření umožňuje verzování, čili stažení určité nastavené verze. Je zde možnost i stažení nejnovější verze. Díky verzování je možné rozšíření jak aktualizovat, tak i downgradovat (nainstalovat starší verzi). V Salt řešení jsou dvě možnosti aktualizace a to přes WP-CLI nebo nástroj Git.
\pagebreak
\\[12pt]Instalace/aktualizace rozšíření pomocí WP-CLI:
\begin{lstlisting}[caption=Instalace/aktualizace rozšíření s WP-CLI]
{%- if plugin.source.engine == 'http' %}
{{ plugin_name }}_install:
  cmd.run:
{%- if plugin.version == 'latest' %}
    - name: wp plugin install {{ plugin_name }}
{%- else %}
    - name: wp plugin install {{ plugin_name }} --version='{{ plugin.version }}'
{%- endif %}
    - cwd: {{ web_path }}
    - user: www-data
\end{lstlisting}
Tento kód se provede pouze, pokud je nastaveno, aby se toto určité rozšíření aktualizovalo přes WP-CLI (http). Před provedením tohoto kódu se musí nejdříve zjistit, je-li dané rozšíření nainstalované, aby se neinstalovalo znovu. Jak již bylo řečeno, kód pro aktualizaci má stejný kód pouze se změnou slova v příkazech z install na update.
\\[12pt]Instalace/aktualizace rozšíření pomocí Gitu:
\begin{lstlisting}[caption=Instalace/aktualizace rozšíření s Gitem]
{%- elif plugin.source.engine == 'git' %}
{{ plugin_name }}_git_update:
  git.latest:
    - name: {{ plugin.source.address }}
{%- if plugin.version != 'latest' %}
    - rev: {{ plugin.version }}
{%- else %}
    - rev: 'master'
{%- endif %}
    - target: {{ web_path }}/wp-content/plugins/{{ plugin_name }}
    - user: www-data
    - force: true
    - require:
      - git: wordpress_{{ app_name }}_git
{%- endif %}
\end{lstlisting}
Při instalaci pomocí Gitu je potřeba vědět adresu, na které jsou přístupné soubory rozšíření a tuto informaci uvést do name části. Pomocí rev (revision) se určuje, jaká verze rozšíření se má stáhnout. Jedna z dalších informací je také cesta, do které mají být rozšíření nainstalovány. Tato cesta se nastavuje pomocí target.

Aby tento kód fungoval musíme použít force: true, protože Git by jinak odmítl přepsat cílové soubory. Proto toto není úplně nejlepší řešení. Vhodnějším by bylo stahovat určité verze rozšíření do vlastního Gitlabu a tam kontrolovat úpravy v souborech. Díky tomu se také dá snadněji oddělit produkční a vývojové prostředí. V produkčním prostředí se nahrávají pouze otestovaná rozšíření a vývojové prostředí je určeno k testování nejnovějších verzí rozšíření, které se poté implementují na produkční prostředí.

Aktualizace jádra je určena pouze proměnnou ano/ne, jestli se má jádro aktualizovat. A jádro jako takové je jediná část v tomto redakčním systému, proto tento kód nemusíme obalovat do žádného cyklu.
\\[12pt]Kód pro aktualizaci jádra:
\begin{lstlisting}[caption=Aktualizace jádra]
{%- if app.do_update.core_update %}
wp_core_update:
  cmd.run:
    - name: wp core update
    - cwd: {{ web_path }}
    - user: www-data
    - unless: wp core check-update
{%- endif %}
\end{lstlisting}
Aktualizace se provede, pokud je v yml nastavena proměnná aktualizace jádra (\verb|core_update|) na true. A díky unless části se aktualizace provede pouze, pokud je k dispozici nová verze systému.
\pagebreak
\\[12pt]Kód pro aktualizaci šablon je skoro stejný jako pro aktualizaci jádra:
\begin{lstlisting}[caption=Aktualizace šablon]
{%- if app.do_update.theme_update %}
wp_theme_update:
  cmd.run:
    - name: wp theme update --all
    - cwd: {{ web_path }}
    - user: www-data
{%- endif %}
\end{lstlisting}
Aktualizování šablon je možné rozpracovat do stejné podoby jako u rozšíření, ale díky nutnosti platit za většinu šablon není možné využít WP-CLI a Git pouze pro některé z nich. Proto je tento postup zatím řešený jako jediný.

\section{Implementace pomocí Ansible}
Ansible jako jediný z použitých nástorojů nefunguje na bázi master/minion, ale pouze posílá soubor příkazů na ovládaný stroj, který se provede a poté se smaže. Díky tomuto je nasazení snadnější, protože není důležité jaký stroj je master a jaký minion. V tomto případě se storoje stále nazývají master a minion, ale v definici Ansible toto nemá žádný význam.

Ansible součást se nasazuje, jak na master stroj, tak na miniona (web03), na kterém budou soubory Wordpressu. Aby spolu mohly stroje komunikovat pomocí Ansible, je nutné aby měly seznam IP adres ostatních strojů ve svém host souboru, proto je tento soubor přítomný na všech strojích.
\\[12pt]Proto se přidají další součásti do konfiguračního souboru mastera:
\begin{lstlisting}[caption=Další master součásti (Ansible)]
classes:
- system.salt.master.formula.ansible
- system.ansible.client.single
- system.ansible.server.single
- system.ansible.server.playbook.wordpress
\end{lstlisting}
Ansible client/server single obsahuje různá nastavení jako SSH klíče, zapnutí service a odkazu na playbook. Důležitá část je Ansible formule, která se stará o instalaci tohoto nástroje a vytvoření uživatelů. Playbook Wordpress na serveru obsahuje umístění playbooku pro miniona a také různé parametry jako IP adressy strojů, které se vkládají do host souboru. Playbook je postup, jakým způsobem se má Wordpress nainstalovat, něco jako formule u nástroje Salt.
\\[12pt]Je potřeba přidat i parametry na master:
\begin{lstlisting}[caption=Další master parametry (Ansible)]
parameters:
  _param:
    ansible_server_environment_repository: git@repo1.robotice.cz:ansible-playbooks
    ansible_server_environment_revision: develop
\end{lstlisting}
Podobné parametry jako u Salt, které se starají o nastavení, kde má Git hledat playbooky pro Ansible a také jaké jejich revision má stahovat. Po doplnění nastavení mastera je na čase zprovoznit samotného miniona, podobně jako tomu bylo u Saltu.
\\[12pt]Nastavení součástí Ansible miniona:
\begin{lstlisting}[caption=Minion součásti (Ansible)]
node:
  wordpress_web_ha_ansible_stg:
    name: web03
    domain: wordpress-ha.dls.vpc.cloudlab.cz
    classes:
    - system.linux.system.single
    - system.openssh.client.cluster.cloudlab
    - system.openssh.server.team.tcpcloud
    - system.ansible.client.single
    params:
      salt_master_host: ${_param:reclass_config_master}
      apache_wordpress_devel_host: wordpress-ansible.robotice.cz
\end{lstlisting}
Salt master host je zde pouze pro možnost komunikací se Salt masterem, v tomto případě není nutný. Přidává se také host, aby se zajistil přístup na webové stránky pomocí url aresy. Tyto úpravy umožnily komunikaci hostů pomocí Ansible a také přístupnost playbooku pro instalaci Wordpressu, proto se přejde k dalšímu kroku a to k vytvoření playbooku a jeho následné instalaci na miniona. Instalaci playbooku se spouští na masteru spustit pomocí příkazu "ansible-playbook název-playbooku.yml".

Ansible využívá pro svoji práci hlavně soubory yml. V předchozím případě se používal soubor sls, ve kterém se mohly definovat proměnné, funkce i cykly. To v tomto případě ale není možné, protože yml je jazyk pro serializaci dat. V Ansible se ale využívají specifické názvy v yml souborech, které zajistí stejné možnosti jako v souboru sls.

\subsection{Instalace WP-CLI}
V případě Ansible se první instaluje WP-CLI, protože se tento nástroj použije ve větším měřítku než v případě Saltu. Následující kód zpravovává jak stažení WP-CLI, tak jeho instalaci.
\\[12pt]Stažení a instalace WP-CLI:
\begin{lstlisting}[caption=Instalace WP-CLI]
- name: install (wp-cli)
  get_url:
    url: https://raw.githubusercontent.com/wp-cli/builds/
          gh-pages/phar/wp-cli.phar
    dest: "{{ wordpress_wp_cli_dir }}/wp"
    force: true
    owner: root
    group: root
    mode: 0755
  tags: [configuration, wordpress, wordpress-wp-cli, wordpress-wp-cli-install]
\end{lstlisting}
Možnost \verb|get_url| umožňuje stahovat soubory pomocí HTTP, HTTPS nebo FTP. Pro stažení je potřebné nastavit url odkaz na soubor, který se má stáhnout. Proměnná dest určuje, kam se má soubor stáhnout. Do této proměnné se vloží informace z \verb|wordpress_wp_cli_dir|, ve které uložena cesta do složky bin, ze které jsou v Linuxu spouštěny uživatelské programy. Stažený soubor se uloží pod jménem wp a díky tomu je v konzoli přístupný pomocí příkazu wp.

Jako další se určuje uživatel, pod kterým se tento soubor ukládá a určují se jeho práva pro přístup. Další proměnné je force, která umožňuje stahovat soubor pokaždé, i když už je v učené složce přítomný. Pro malé soubory opětovné stahování nedělá v Ansible žádný problém. A poslední je možnost tags, která umožňuje spustit pouze jednu určitou část z celého playbooku. Tato možnost se hodí například pro spuštění pouze aktualizace Wordpressu.

\subsection{Instalace jádra WP}
Při instalaci jádra se zajišťuje i stažení Wordpressu, proto se kontroluje, jestli jsou soubory už přítomné v dané složce. Pokud soubory existují na správném místě, pak se nebude instalace provádět znovu. Jak již bylo řečeno, nedají se využít funkce if nebo for, a proto je vytvořen úkol, který se stará o tuto kontrolu.
\\[12pt]Kontrola Wordpress souborů:
\begin{lstlisting}[caption=Kontrola WP souborů]
- name: check if wp is downloaded
  shell: "ls {{ item.path }} | grep -q 'wp-'"
  register: check_download
  failed_when: False
  changed_when: False
  with_items: wordpress_installs
  tags: [configuration, wordpress, wordpress-core, wordpress-is-downloaded]
\end{lstlisting}
Pro přehlednost pro uživatele je tento úkol pojmenován pomocí name. Nejdůležitější informace v tomto úkolu jsou Linuxový příkaz na kontrolu souborů, \verb|with_items| a také register. Linuxový příkaz ls vypisuje soubory v určité složce, jaká je tato složka, je nastaveno v proměnné item.path. K proměnným se přistupuje pomocí již zmíněného \verb|with_items|, který umí také přistoupit k proměnným jiných úkolů. Poslední důležitá informace register umožňuje nastavit název úkolu, pod kterým je přístupný jiným úkolům. Register je nastaven hlavně z důvodu, aby byly přístupné proměnné tohoto úkolu, protože nahrazuje kontrolu if.

Další parametry jsou \verb|failed_when|, \verb|changed_when| a také tags, který je popsán u minulého kódu. Díky možnosti \verb|failed_when| je možné definovat, kdy Ansible vrátí informaci, že se úkol neprovedl. Pak je také potřeba někdy negovat zpáteční hodnotu, což zajiťuje parametr \verb|changed_when|. Ani jedna z těchto možností v tomto případě využita není, a proto mají nastavenou hodnotu false.

Všechny následující úkoly budou využívat příkazu wp, který poskytuje WP-CLI. Pokud nejsou stažené soubory Wordpressu, tak se musí stáhnout. K tomu je využit Linuxový příkaz wp core download.
\\[12pt]Stažení souborů Wordpressu:
\begin{lstlisting}[caption=Stažení WP souborů]
- name: download wp files
  shell: "wp core download"
  args:
    chdir: {{ item.item.path }}
  with_items: check_download.results
  when: wordpress_installs and item.rc != 0
  sudo: yes
  sudo_user: {{ item.item.user }}
  tags: [configuration, wordpress, wordpress-core, wordpress-downloaded]
\end{lstlisting}
Tento úkol se spustí pouze, pokud předchozí kontrola vrátí hodnotu 1 (true). V Linuxu jsou významy false a true prohozeny, takže příkaz ls vrátí hodnotu 1, pokud nenajde žádné soubory obsahující "wp-" v určené složce. Pro přístup k této proměnné se musí použít \verb|with_items| s názvem, který byl nastaven pomocí register. Přerušení tohoto úkolu se zajistí pomocí části when, která určuje, kdy se má úkol přerušit.

Aby se nemusel u příkazu wp core využívat parametr --path, dá se použít Ansible argument chdir, který změní umístění na určenou složku. Tato složka je také nastavena v proměnných. Jedno z posledních nastavení je sudo a \verb|sudo_user|, které umožňuje změnit uživatele z root (administrátor) na uživatele zadaného v proměnných. Díky tomu se použije uživatel, který je určený na správu Wordpressu a také se nemusí využívat parametr --allow-root pro WP-CLI příkazy.

\subsection{Vytvoření souboru wp-config}
Po úspěšné instalci jádra je třeba vytvořit soubor wp-config. V případě Saltu se využíval soubor, do kterého se vložily proměnné z yml, a poté se tento soubor přesunul na miniona. V tomto případě se používá druhá možnost a to konfigurace pomocí WP-CLI. Výhodou je, že se tento soubor vytváří přesně podle šablony dané verze Wordpressu, ale nevýhodou je, že automaticky ho není možné upravit více než dovoluje WP-CLI.
\\[12pt]Vytváření souboru wp-config:
\begin{lstlisting}[caption=Soubor wp-config]
- name: create wp-config
  shell: "wp core config --quiet --dbname='{{ item.dbname }}' --dbuser='{{ item.dbuser }}' --dbpass='{{ item.dbpass }}' --dbhost='{{ item.dbhost | default('localhost') }}'"
  args:
    creates: "{{ item.path }}/wp-config.php"
    chdir: {{ item.path }}
  with_items: wordpress_installs
  sudo: yes
  sudo_user: {{ item.item.user }}
  tags: [configuration, wordpress, wordpress-core, wordpress-configure]
\end{lstlisting}
Přikaz wp core config vytvoří soubor wp-config a naplní ho proměnnými, které jsou uložené ve \verb|wordpress_installs|. Je vhodné tomuto úkolu nastavit také argument creates, aby nebyl soubor wp-config vytvářen pokaždé. Znovu vytvářením by nejen zpomaloval další úkoly, ale také by mohl přepisovat úpravy provedené Wordpressem nebo administrátorem. Tomuto úkolu se nenastavuje hodnota register, protože na tomto úkolu nejsou nutně závislé žádné další úkoly.

\subsection{Instalace databáze}
Při instalaci databáze se musí kontrolovat, jestli už není naistalována. Pokud by kód pro její vytvoření projížděl pokaždé, tak by se do databáze vkládaly výchozí (defaultní) data. Vkládáním výchozích dat by se mazaly změny provedené v administraci Wordpressu. Kód pro kontrolu je velice podobný jako byl kód pro kontrolu souborů Wordpressu.
\pagebreak
\\[12pt]Kontrola před instalací databáze:
\begin{lstlisting}[caption=Kontrola databáze]
- name: check if database is already installed
  shell: "wp core is-installed --allow-root"
  args:
    chdir: {{ item.path }}
  register: check_installation
  failed_when: False
  changed_when: False
  with_items: wordpress_installs
  tags: [configuration, wordpress, wordpress-core, wordpress-is-installed]
\end{lstlisting}
Příkaz wp core is-installed kontroluje, jestli jsou Wordpress tabulky přítomné v databázi. Tento příkaz kontroluje pouze hlavní tabulky Wordpressu, nikoliv tabulky přidané pro rozšíření.

Pokud tedy nejsou tabulky v databázi, tak se musí vytvořit. Do tabulek je také potřeba vložit výchozí hodnoty, které automaticky vytvoří WP-CLI z dodaných parametrů. Jedny z těhto parametrů jsou administrátorský uživatel a jeho heslo.
\\[12pt]Instalace databáze:
\begin{lstlisting}[caption=Instalace databáze]
- name: install wp database
  shell: "wp core install --allow-root --url='{{ item.item.url }}' --title='{{ item.item.title }}' --admin_name='{{ item.item.admin_name | default('admin') }}' --admin_email='{{ item.item.admin_email }}' --admin_password='{{ item.item.admin_password }}'"
  args:
    chdir: {{ item.item.path }}
  with_items: check_installation.results
  when: wordpress_installs and item.rc != 0
  tags: [configuration, wordpress, wordpress-core, wordpress-install]
\end{lstlisting}
Díky příkazu wp core install a jeho parametrům se nainstaluje jádro Wordpressu. V tomto případě se nepřistupuje k proměnným přímo, ale přes kontrolu instalace, proto je v příkazu využito item.item místo item. Po instalaci je možné znovu použít příkaz wp core is-installed, aby se zkontrolovalo, jestli byl Wordpress správně nainstalován. Pokud někde v instalaci nastala chyba, pak se další úkoly neprovádí a vypíše se chybová hláška.

\subsection{Instalace rozšíření a šablon}
Kód pro instalaci rozšíření a šablon je kompletně stejný až na klíčové slovo ve WP-CLI příkazu. Prvním krokem je kontrola, jestli je rozšíření nainstalováno, aby se mohlo určit, jestli se jedná o instalaci nebo aktualizaci.
\\[12pt]Kontrola přítomnosti rozšíření/šablony:
\begin{lstlisting}[caption=Kontrola rozšíření/šablony]
- name: identify installation plugin
  shell: "wp plugin is-installed --allow-root {{ item.1 }}"
  args:
    chdir: {{ item.0.path }}
  register: check_installation_plugins
  failed_when: False
  changed_when: False
  with_subelements:
    - wordpress_installs
    - plugins
  when: item.1
  tags: [configuration, wordpress, wordpress-plugins, wordpress-is-installed-plugin]
\end{lstlisting}
Kontroly probíhají pomocí příkazu wp plugin is-installed a wp theme is-installed. V tomto případě se přistupuje nejen k proměnným ale také k poli proměnných, které je podřazené jiné proměnné. K tomu se využívá možnost \verb|with_subelements| a pro přístup k proměnným se využije klíčové slovo item a číslo subelementu, ve kterém je informace uložena (začíná od 0). Pomocí when se také určuje, aby se kód neprováděl, pokud není žádné další rozšíření definovano a mohlo se pokračovat dál.

Po kontrole se může přejít k instalaci nebo aktualizaci. Pokud rozšíření není přítomno, tak se nainstaluje pomocí příkazu wp plugin install a wp theme install. Pokud rozšíření nebo šablona s definovaným jménem neexistuje, pak se nenainstaluje a příkaz selže. Existence jména ve WP-CLI se kontroluje pouze se seznamem na Wordpress.org, který obsahuje pouze pluginy zdarma ke stažení.
\\[12pt]Kontrola přítomnosti rozšíření/šablony:
\begin{lstlisting}[caption=Kontrola rozšíření/šablony]
- name: install plugin
  shell: "wp plugin install {{ item.item.1 }} --allow-root"
  args:
    chdir: {{ item.item.0.path }}
  with_items: check_installation_plugins.results
  when: check_installation_plugins is defined and item.item.1 and item.rc != 0
  tags: [configuration, wordpress, wordpress-plugins, wordpress-install-plugin]
\end{lstlisting}
Tento kód se provede, pouze pokud předchozí kontrola vrátí hodnotu 1 (true) a rozšíření je definováno. Znovu se také přistupuje k proměnným pomocí předchozího úkolu, a proto se zadává item.item. Po tomto kódu se znovu projíždí kontrola, jestli bylo rozšíření nainstalováno, aby se zamezilo dalším chybám a vynutila se kontrola konfigurace.

\subsection{Instalace aktualizací}
Aktualizace jádra, rozšíření i šablon se provádí pouze, pokud je nastavena proměnná pro jejich aktualizace na true a jsou-li nainstalované, aby nevznikaly chyby v konfiguraci.
\\[12pt]Kód pro aktualizaci jádra:
\begin{lstlisting}[caption=Aktualizace jádra (Ansible)]
- name: update wp core
  shell: "wp core update --allow-root"
  args:
    chdir: {{ item.item.path }}
  with_items: check_installation.results
  when: wordpress_installs and item.rc == 0 and item.item.core_update == 1
  tags: [configuration, wordpress, wordpress-core, wordpress-update]
\end{lstlisting}
Díky modulu when se všechny kontroly před spuštěním spojí do jedné podmínky. Přístup k proměnným je znovu pomocí item.item, jediná možnost jak použít pouze jeden item je vložit do \verb|with_items| další položku, ale pak by přístup k těmto proměnným byl pomocí item.0 a item.1.
\\[12pt]Aktualizace rozšíření a šablon:
\begin{lstlisting}[caption=Aktualizace rozšíření a šablon (Ansible)]
- name: update plugin
  shell: "wp plugin update {{ item.item.1 }} --allow-root"
  args:
    chdir: {{ item.item.0.path}}
  with_items: check_installation_plugins.results
  when: check_installation_plugins is defined and item.item.1 and item.rc == 0 and item.item.0.plugins_update == 1
  tags: [configuration, wordpress, wordpress-plugins, wordpress-update-plugin]
\end{lstlisting}
Všechny části tohoto kódu již byly popsány v předchozích příkladech. Toto řešení je v tomto stavu kompletní a plně použitelné. Další možnost je využít Git pro lepší kontrolu nad celým projektem.

\subsection{Nasazení s využitím Gitu}
Pro Git je nejlepší vytvořit kopii stávajícího řešení s jiným názvem. Pokud by byly úkoly pro Git a WP-CLI v jednom řešení, pak by to velice zpomalovalo nasazení. Důvodem je to, že by se prováděly kontroly obou řešení místo jednoho. Pro toto nasazení má Ansible modul pro komunikaci s Gitem.
\pagebreak
\\[12pt]Ansible s využitím Gitu:
\begin{lstlisting}[caption=Instalace jádra Wordpressu pomocí Git]
- name: download wp files via git
  git: repo={{ item.item.core_path_git }} dest={{ item.item.path }} version={{ item.item.core_version }}
  with_items: check_download_git.results
  when: wordpress_installs_git and item.rc != 0
  sudo: yes
  sudo_user: {{ item.item.user }}
  tags: [configuration-git, wordpress-git, wordpress-core-git, wordpress-downloaded-git]
\end{lstlisting}
Pro modul Git jsou dvě hlavní informace. První je repo, která určuje odkud se budou soubory stahovat. Druhá je cíl (dest), kam se soubory mají stáhnout. Vedlejší informace verze (version) určuje, jakou verzi má Git stahovat a díky tomu umožní jak aktualizaci, tak i stažení předchozí verze (downgrade).

Další úkoly budou pouhé kombinace předchozích s využitím nástroje Git.

\section{Puppet}
Nasazení pomocí Puppetu probíhá pomocí funkcí tohoto nástroje s využitím Linuxových příkazů, které stahují a pracují se soubory. Toto řešení obsahuje pouze implementaci Wordpressu bez rozšíření. Je tomu tak z technických důvodů, které jsou problémy s cloud rozhraním a není plná funkčnost reclassu pro Puppet. Proto se tato implementace skládá z vytvoření databáze a Wordpress souborů.
\\[12pt]Jako v předchozích případech se nejdříve musí přidat součásti do master stroje:
\begin{lstlisting}[caption=Další master součásti (Puppet)]
classes:
- system.puppet.master.single
- system.puppet.master.module.wordpress
- system.hiera.storage.puppet
parameters:
  _param:
    hiera_data_repository: git@repo1.robotice.cz:hiera-models/dels-puppet-model.git
    hiera_data_revision: master
\end{lstlisting}
Součást hiera se využívá jako částečná náhrada za reclass, a proto potřebuje podobné informace jako reclass. Znovu se zadává i odkaz na modul, který nainstaluje Wordpress na miniona. Po dokončení nastavení mastera je načase přidat součásti minionovi.
\\[12pt]Nastavení součástí Puppet miniona:
\begin{lstlisting}[caption=Minion součásti (Puppet)]
node:
  wordpress_web_ha_puppet_stg:
    name: web02
    domain: wordpress-ha.dls.vpc.cloudlab.cz
    classes:
    - system.linux.system.single
    - system.openssh.client.cluster.cloudlab
    - system.openssh.server.team.tcpcloud
    - system.puppet.agent.master
    - system.ansible.client.single
    params:
      salt_master_host: ${_param:reclass_config_master}
      puppet_agent_master_host: ${_param:reclass_config_master}
      puppet_agent_report_host: ${_param:reclass_config_master}
\end{lstlisting}
Většina využitých tříd je stejná jako v předchozích případech. Jediná nová je pro Puppet agenta (miniona). Pro miniona je také důležité zajistit možnost komunikace s master strojem, proto je potřeba nastavit IP adresu master stroje. Tato adresa je stejná jako v případě Saltu a díky tomu se nemusí definovat dvakrát.

Tyto úpravy umožnily nastavení součástí pro oba stroje. Další úkol je vytvořit modul, který nainstaluje Wordpress na miniona. Puppet využívá definování tříd podobně jako PHP, a proto se musí nejdříve takové třídy vytvořit jak pro Wordpress, tak pro databázi.
\pagebreak
\\[12pt]Třída pro Wordpress v Puppetu:
\begin{lstlisting}[caption=Vytvoření třídy pro Wordpress (Puppet)]
define wordpress::instance::app ( $parametry ) {
- Zde budou kontroly parametrů a vytvoření WP souborů.
}
\end{lstlisting}
Stejný způsob by se použil pro vytvoření tříd pro rozšíření a šablony. Po vytvoření tříd se zpracuje jejich plnění parametry a dalšími funkcemi. Instalace jako taková se provede pouze zavoláním třídy s parametry.

\subsection{Vytvoření Wordpress souborů}
Tato část se nachází ve tříde pro Wordpress a obsahuje kontrolu, jestli jsou všechny důležité parametry nastaveny a poté zajistí samotné vytvoření Wordpress složky se soubory. Kontroluje se také, jestli má proměnná správný formát. Některé proměnné mohou být pouze pravda/nepravda (boolean), jiné třeba textové (string). Po kontrolách se přechází ke stažení Wordpress souborů.
\\[12pt]Stažení souborů s nástrojem Puppet:
\begin{lstlisting}[caption=Stažení Wordpressu (Puppet)]
exec { "Download Wordpress ${install_url}/wordpress-${version}.tar.gz to ${install_dir}":
  command => "wget ${install_url}/wordpress-${version}.tar.gz",
  creates => "${install_dir}/wordpress-${version}.tar.gz",
  require => File[$install_dir],
  user    => $wp_owner,
  group   => $wp_group,
}
\end{lstlisting}
Stažení probíhá pomocí Linuxového příkazu wget, který stahuje z HTTP, HTTPS nebo FTP. Tomuto kódu se definuje možnost creates, podobně jako v Ansible, protože lokálně vytváří stažený soubor. Další proměnné určují uživatele, pod kterým je soubor vytvořen a jestli má práva pro zápis do určené složky. A stejně jako v Ansible je možné tuto funkci pojmenovat, aby bylo jasné, že se právě zpracovává.

Soubor, který se stahuje, má koncovku tar.gz, což říká, že je to archiv. Když je to archiv, tak se musí nejdříve rozbalit. K tomu se využije Linuxová funkce tar. Následně se změní vlastník souborů pomocí příkazu chown. Po těchto úpravách jsou připravené Wordpress soubory ve složce, která byla určena v proměnných, a proto se může přejít k vytvoření souboru wp-config.

\subsection{Vytvoření souboru wp-config}
V Pupetu se využívá šablonovací systém, proto je vytvořena šablona souboru wp-config, stejně jako tomu bylo v případě Saltu. Tato šablona se poté naplní informacemi z proměnných. Díky tomu se nemusí soubor nastavovat ručně a je možné ho velice snadno upravit.
\\[12pt]Vytvoření souboru wp-config pomocí šablony v Puppetu:
\begin{lstlisting}[caption=Vytvoření souboru wp-config]
concat::fragment { "${install_dir}/wp-config.php body":
  target  => "${install_dir}/wp-config.php",
  content => template('wordpress/wp-config.php.erb'),
  order   => '20',
}
\end{lstlisting}
S použitím concat::fragment se dá složit více souborů do jednoho kompletního a přesunout do umístění ve kterém má být. Samotné vložení informací do souboru zajišťuje funkce template. Pokud se skládá více souborů dohromady je potřeba určit v jakém pořadí se mají složi. K tomuto řazení se nastavuje proměnná order. Po dokončení těchto funkcí jsou kompletní soubory Wordpressu a jediné co zbývá je instalace databáze.

\subsection{Instalace databáze}
Pro vyvoření MySQL databáze se může využít Linuxových příkazů, ale Puppet má pro tuto práci rozšíření, které usnadňuje práci s databází. Tento modul má mnoho funkcí, ale v tomto případě se použije pouze pro vytvoření uživatele a databáze.
\pagebreak
\\[12pt]Vytvoření databáze pomocí Puppet modulu:
\begin{lstlisting}[caption=Vytvoření databáze]
mysql_database { "${db_host}/${db_name}":
  name => $db_name,
  charset => 'utf8',
}
\end{lstlisting}
Jediné co je potřeba nastavit v tomto příkazu je jméno databáze, které se musí shodovat se jménem uvedeným v souboru wp-config.

Vytvoření uživatele do databáze se používá nejčastěji pro omezení práv, aby uživatel mohl upravovat jen svoji přidělenou databázi a nezasahoval do žádné jiné. V tomto případě ale není problém vytvořit uživatele s právy administrátora, protože web je pouze jeden na serveru a také je pouze pro testování, nikoliv pro produkční využití.
\\[12pt]Vytvoření uživatele databáze a nastavení jeho práv:
\begin{lstlisting}[caption=Vytvoření uživatele]
mysql_user { "${db_user}@${db_host}":
    password_hash => mysql_password($db_password),
}

mysql_grant { "${db_user}@${db_host}/${db_name}.*":
  table      => "${db_name}.*",
  user       => "${db_user}@${db_host}",
  privileges => ['ALL'],
}
\end{lstlisting}
Po spuštění tohoto kódu by měl být na určeném stroji plně funkční Wordpress. Pro dokončení instalace je ovšem třeba naplnit databázi základními daty. Toho lze dosáhnout pomocí zadání url adresy webu do prohlížeče nebo vložením dat ze souboru pomocí Linuxového příkazu, jako tomu bylo v Saltu.
\pagebreak

\subsection{Rozšíření a šablony}
Instalace rozšíření a šablon tímto způsobem je velice podobná instalaci pomocí WP-CLI, proto by se tohoto rozšíření dalo využít a ovládat přes Linuxové příkazy podobně jako v případě Ansible. Šlo by tedy o vytvoření tříd, kontrolu proměnných a volání funkcí WP-CLI. 