Palvelinten hallinta - Harjoitus 3 ============== *Disclaimer:* -------------- Tämä harjoitus on tehty osana Haaga-Helian Tietojenkäsittelyn koulutusohjelman kurssia [Palvelinten hallinta (ICT4TN022, kevät 2018)](http://www.haaga-helia.fi/fi/opinto-opas/opintojaksokuvaukset/ICT4TN022). Kurssin pitäjänä toimii [Tero Karvinen](http://terokarvinen.com/), joka on määritellyt tämän harjoituksen tehtävänkuvaukset. Tehtävien vastaukset ovat Pekka Heleniuksen (allekirjoittanut) tuottamia. *SISÄLLYSLUETTELO* -------------- - [b) Tiedosto muotista: tee yksinkertainen SLS-tilatiedosto, joka laittaa muuttujan tiedostoon. Käytä jinjan kontekstimuuttujaa (template: jinja, context: ...)](https://github.com/Fincer-altego/central-management-of-multiple-servers/blob/master/h3.md#b-tiedosto-muotista-tee-yksinkertainen-sls-tilatiedosto-joka-laittaa-muuttujan-tiedostoon-k%C3%A4yt%C3%A4-jinjan-kontekstimuuttujaa-template-jinja-context-) - [c) SLS tilaa Jinjalla: tee yksinkertainen SLS-tilatiedosto, joka käyttää for-in -silmukaa. Voit esimerkiksi tehdä kolme tiedostoa silmukalla. (Tässä tehtävässä siis käytetään jinjaa vain SLS-tiedoston sisällä, älä sotke samaan esimerkkiin tekstitiedostojen sisällön muuttamista.)](https://github.com/Fincer-altego/central-management-of-multiple-servers/blob/master/h3.md#c-sls-tilaa-jinjalla-tee-yksinkertainen-sls-tilatiedosto-joka-k%C3%A4ytt%C3%A4%C3%A4-for-in--silmukaa-voit-esimerkiksi-tehd%C3%A4-kolme-tiedostoa-silmukalla-t%C3%A4ss%C3%A4-teht%C3%A4v%C3%A4ss%C3%A4-siis-k%C3%A4ytet%C3%A4%C3%A4n-jinjaa-vain-sls-tiedoston-sis%C3%A4ll%C3%A4-%C3%A4l%C3%A4-sotke-samaan-esimerkkiin-tekstitiedostojen-sis%C3%A4ll%C3%B6n-muuttamista) - [d) SSH-demonin portti: tee tila, joka asentaa SSH-demonin valittuun porttiin. Käytä portin valintaan Jinjaa, siten että sshd_config:issa “Port:”-kohdan arvo tulee Jinjan muuttujasta.](https://github.com/Fincer-altego/central-management-of-multiple-servers/blob/master/h3.md#d-ssh-demonin-portti-tee-tila-joka-asentaa-ssh-demonin-valittuun-porttiin-k%C3%A4yt%C3%A4-portin-valintaan-jinjaa-siten-ett%C3%A4-sshd_configissa-port-kohdan-arvo-tulee-jinjan-muuttujasta) - [e) Kokeile jonkun toisen opiskelijan tekemää Salt-tilaa. Kokeiltava tila voi olla mistä vain harjoituksesta. Opiskelijoiden raportteja ja koodeja löydät tämän sivun perästä kommenteista.](https://github.com/Fincer-altego/central-management-of-multiple-servers/blob/master/h3.md#e-kokeile-jonkun-toisen-opiskelijan-tekem%C3%A4%C3%A4-salt-tilaa-kokeiltava-tila-voi-olla-mist%C3%A4-vain-harjoituksesta-opiskelijoiden-raportteja-ja-koodeja-l%C3%B6yd%C3%A4t-t%C3%A4m%C3%A4n-sivun-per%C3%A4st%C3%A4-kommenteista) **b)** Tiedosto muotista: tee yksinkertainen SLS-tilatiedosto, joka laittaa muuttujan tiedostoon. Käytä jinjan kontekstimuuttujaa (template: jinja, context: ...). -------------- **Vastaus:** Luodaan tiedosto _/srv/salt/firstninja.sls_ seuraavalla sisällöllä (sudo nano /srv/salt/firstninja.sls): (Tehtävänannon vaatimus täyttyy state:ssa _put_my_foo_stuff_) ``` # Author: Pekka Helenius (~Fincer), 2018 hostile_secondgroup: group.present: - name: foobar - gid: 666 - system: True hostile_user: user.present: - name: evilninja - fullname: Evil Ninja - uid: 666 - gid: 666 - shell: /bin/bash - home: /home/foo - groups: - foobar - require: - group: hostile_secondgroup put_my_foo_stuff: file.managed: - name: /foo/mysecretfoo - source: salt://foofile - makedirs: True - user: 666 - group: 666 - mode: 0744 - template: jinja - context: supersecretfoo: 'you never know where this came from' notsosecretbar: 'wanna beer?' - require: - user: hostile_user foo_executable: file.symlink: - name: /usr/local/bin/mysecretfoo - target: /foo/mysecretfoo - require: - file: put_my_foo_stuff evil_nullfiles: cmd.run: - name: 'touch ./foo_everywhere' - cwd: /foo - creates: foo_everywhere - creates: foofoo - require: - file: put_my_foo_stuff identity_crisis: cmd.run: - name: /usr/bin/id -a - runas: evilninja - require: - user: hostile_user haha_execute: cmd.run: - shell: /bin/sh - name: mysecretfoo - require: - user: hostile_user - file: foo_executable ``` Lisätään masterille tiedosto _/srv/salt/foofile_ seuraavalla sisällöllä (sudo nano /srv/salt/foofile): ``` #!/bin/sh echo -e "{{ supersecretfoo }}\n{{ notsosecretbar }}" ``` Tämä tiedosto kirjoitetaan minionin/minioneiden kohteeseen _/foo/mysecretfoo_ ja luodaan symbolinen linkki _/usr/local/bin/mysecretfoo_. Testataan toimivuus harjoituksessa 1 ja 2 käytetyllä master-minion -tietokonekokoonpanolla (master: master, minion: orjakone): ``` sudo salt 'orjakone' state.apply firstninja ``` Masterilla tulostettu output: ``` orjakone: ---------- ID: hostile_secondgroup Function: group.present Name: foobar Result: True Comment: Group foobar is present and up to date Started: 21:52:22.010941 Duration: 1.317 ms Changes: ---------- ID: hostile_user Function: user.present Name: evilninja Result: True Comment: User evilninja is present and up to date Started: 21:52:22.012741 Duration: 13.69 ms Changes: ---------- ID: put_my_foo_stuff Function: file.managed Name: /foo/mysecretfoo Result: True Comment: File /foo/mysecretfoo is in the correct state Started: 21:52:22.027375 Duration: 10.438 ms Changes: ---------- ID: foo_executable Function: file.symlink Name: /usr/local/bin/mysecretfoo Result: True Comment: Created new symlink /usr/local/bin/mysecretfoo -> /foo/mysecretfoo Started: 21:52:22.038030 Duration: 26.087 ms Changes: ---------- new: /usr/local/bin/mysecretfoo ---------- ID: evil_nullfiles Function: cmd.run Name: touch ./foo_everywhere Result: True Comment: Command "touch ./foo_everywhere" run Started: 21:52:22.066037 Duration: 8.669 ms Changes: ---------- pid: 3426 retcode: 0 stderr: stdout: ---------- ID: identity_crisis Function: cmd.run Name: /usr/bin/id -a Result: True Comment: Command "/usr/bin/id -a" run Started: 21:52:22.074865 Duration: 158.997 ms Changes: ---------- pid: 3450 retcode: 0 stderr: stdout: uid=666(evilninja) gid=666(foobar) groups=666(foobar) ---------- ID: haha_execute Function: cmd.run Name: mysecretfoo Result: True Comment: Command "mysecretfoo" run Started: 21:52:22.234242 Duration: 14.473 ms Changes: ---------- pid: 3455 retcode: 0 stderr: stdout: -e you never know where this came from wanna beer? Summary for orjakone ------------ Succeeded: 7 (changed=4) Failed: 0 ------------ Total states run: 7 Total run time: 233.671 ms ``` **c)** SLS tilaa Jinjalla: tee yksinkertainen SLS-tilatiedosto, joka käyttää for-in -silmukaa. Voit esimerkiksi tehdä kolme tiedostoa silmukalla. (Tässä tehtävässä siis käytetään jinjaa vain SLS-tiedoston sisällä, älä sotke samaan esimerkkiin tekstitiedostojen sisällön muuttamista.) -------------- **Vastaus:** Luodaan master:lle tiedosto _/srv/salt/first_jinjaloop.sls_ seuraavalla sisällöllä (sudo nano /srv/salt/first_jinjaloop.sls): ``` # Author: Pekka Helenius (~Fincer), 2018 {% for loplop in ['round_1', 'round_2', 'round_3', 'round_4'] %} loopsloops_noops{{ loop.index }}: file.managed: - name: /tmp/loopnoops/{{ loplop }} - source: salt://loops/jinjaninja_loop - makedirs: True - template: jinja - context: filenumber: {{ loplop }} run_fatboy_run_{{ loop.index }}: cmd.run: - name: cat /tmp/loopnoops/{{ loplop }} - require: - file: loopsloops_noops{{ loop.index }} {% endfor %} ``` Luodaan masterilla tiedosto */srv/salt/loops/jinjaninja_loop*: ``` sudo mkdir -p /srv/salt/loops echo "Loops loops noops {{ filenumber }}" | sudo tee /srv/salt/loops/jinjaninja_loop ``` Ajetaan luotu state-tiedosto masterilta orjakone-minionille: ``` sudo salt 'orjakone' state.apply first_jinjaloop ``` Masterilta saatu output: ``` orjakone: ---------- ID: loopsloops_noops1 Function: file.managed Name: /tmp/loopnoops/round_1 Result: True Comment: File /tmp/loopnoops/round_1 updated Started: 22:15:48.402678 Duration: 22.99 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: run_fatboy_run_1 Function: cmd.run Name: cat /tmp/loopnoops/round_1 Result: True Comment: Command "cat /tmp/loopnoops/round_1" run Started: 22:15:48.426279 Duration: 9.155 ms Changes: ---------- pid: 3654 retcode: 0 stderr: stdout: Loops loops noops round_1 ---------- ID: loopsloops_noops2 Function: file.managed Name: /tmp/loopnoops/round_2 Result: True Comment: File /tmp/loopnoops/round_2 updated Started: 22:15:48.435550 Duration: 18.288 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: run_fatboy_run_2 Function: cmd.run Name: cat /tmp/loopnoops/round_2 Result: True Comment: Command "cat /tmp/loopnoops/round_2" run Started: 22:15:48.454122 Duration: 5.179 ms Changes: ---------- pid: 3656 retcode: 0 stderr: stdout: Loops loops noops round_2 ---------- ID: loopsloops_noops3 Function: file.managed Name: /tmp/loopnoops/round_3 Result: True Comment: File /tmp/loopnoops/round_3 updated Started: 22:15:48.459403 Duration: 19.723 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: run_fatboy_run_3 Function: cmd.run Name: cat /tmp/loopnoops/round_3 Result: True Comment: Command "cat /tmp/loopnoops/round_3" run Started: 22:15:48.479414 Duration: 6.602 ms Changes: ---------- pid: 3658 retcode: 0 stderr: stdout: Loops loops noops round_3 ---------- ID: loopsloops_noops4 Function: file.managed Name: /tmp/loopnoops/round_4 Result: True Comment: File /tmp/loopnoops/round_4 updated Started: 22:15:48.486128 Duration: 18.883 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: run_fatboy_run_4 Function: cmd.run Name: cat /tmp/loopnoops/round_4 Result: True Comment: Command "cat /tmp/loopnoops/round_4" run Started: 22:15:48.505300 Duration: 9.609 ms Changes: ---------- pid: 3660 retcode: 0 stderr: stdout: Loops loops noops round_4 Summary for orjakone ------------ Succeeded: 8 (changed=8) Failed: 0 ------------ Total states run: 8 Total run time: 110.429 ms ``` **d)** SSH-demonin portti: tee tila, joka asentaa SSH-demonin valittuun porttiin. Käytä portin valintaan Jinjaa, siten että sshd_config:issa “Port:”-kohdan arvo tulee Jinjan muuttujasta. -------------- **Vastaus:** Halusin kokeilla jinja:lla lukujen generointia tässä tehtävässä. Olisi voitu toki käyttää ennalta määriteltyä porttia, mutta hauskempaa generoida jotain satunnaista. Soveltuuko tämä käyttökohteeseen, it's up to you. SSH-portti generoidaan väliltä 23-600. Käytetään seuraavaa sisältöä uuteen state-tiedostoon. Luodaan masterille tiedosto _srv/salt/ssh_random/init.sls_ (sudo mkdir -p /srv/salt/ssh_random && sudo nano /srv/salt/ssh_random/init.sls): ``` # Author: Pekka Helenius (~Fincer), 2018 {% set supersecret_ssh_port = range(23, 600) | random %} check_sshd_install: pkg.installed: - pkgs: - openssh-server # Ubuntu specific check_sshd_config: file.managed: - name: /etc/ssh/sshd_config - require: - pkg: check_sshd_install check_sshd_current_port: cmd.run: - name: 'echo "current SSH daemon port for $(hostname) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"' - require: - file: check_sshd_config prevent_if_ssh_sessions_open: cmd.run: - names: - 'SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi' - unset SSH_SESSIONS - require: - file: check_sshd_config - cmd: check_sshd_current_port ssh_port: cmd.run: - name: 'sed -i -r "s/^[#P]+ort [0-9][0-9]*/Port {{ supersecret_ssh_port }}/" /etc/ssh/sshd_config' - require: - cmd: prevent_if_ssh_sessions_open sshd_restart: service.running: - name: ssh.service # Yes, this is the daemon process - watch: - cmd: ssh_port ssh_new_port_inform: cmd.run: - name: 'echo "new SSH daemon port for $(hostname) is {{ supersecret_ssh_port }}"' - require: - service: sshd_restart - cmd: ssh_port ``` Ajetaan ssh_random -state masterilta kaikille yhteydessä oleville minioneille: ``` sudo salt '*' state.apply ssh_random ``` Masterilla saatu output minionille "orjakone": ``` orjakone: ---------- ID: check_sshd_install Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 11:14:51.005448 Duration: 449.647 ms Changes: ---------- ID: check_sshd_config Function: file.managed Name: /etc/ssh/sshd_config Result: True Comment: File /etc/ssh/sshd_config exists with proper permissions. No changes made. Started: 11:14:51.457698 Duration: 1.118 ms Changes: ---------- ID: check_sshd_current_port Function: cmd.run Name: echo "current SSH daemon port for $(hostname) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)" Result: True Comment: Command "echo "current SSH daemon port for $(hostname) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"" run Started: 11:14:51.459390 Duration: 4.195 ms Changes: ---------- pid: 2817 retcode: 0 stderr: stdout: current SSH daemon port for minion is: Port 22 ---------- ID: prevent_if_ssh_sessions_open Function: cmd.run Name: SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi Result: True Comment: Command "SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi" run Started: 11:14:51.464445 Duration: 12.004 ms Changes: ---------- pid: 2820 retcode: 0 stderr: stdout: ---------- ID: prevent_if_ssh_sessions_open Function: cmd.run Name: unset SSH_SESSIONS Result: True Comment: Command "unset SSH_SESSIONS" run Started: 11:14:51.476790 Duration: 3.682 ms Changes: ---------- pid: 2827 retcode: 0 stderr: stdout: ---------- ID: ssh_port Function: cmd.run Name: sed -i -r "s/^[#P]+ort [0-9][0-9]*/Port 199/" /etc/ssh/sshd_config Result: True Comment: Command "sed -i -r "s/^[#P]+ort [0-9][0-9]*/Port 199/" /etc/ssh/sshd_config" run Started: 11:14:51.480849 Duration: 3.743 ms Changes: ---------- pid: 2828 retcode: 0 stderr: stdout: ---------- ID: sshd_restart Function: service.running Name: ssh.service Result: True Comment: Service restarted Started: 11:14:51.510980 Duration: 32.241 ms Changes: ---------- ssh.service: True ---------- ID: ssh_new_port_inform Function: cmd.run Name: echo "new SSH daemon port for $(hostname) is 199" Result: True Comment: Command "echo "new SSH daemon port for $(hostname) is 199"" run Started: 11:14:51.543628 Duration: 4.88 ms Changes: ---------- pid: 2838 retcode: 0 stderr: stdout: new SSH daemon port for minion is 199 Summary for orjakone ------------ Succeeded: 8 (changed=6) Failed: 0 ------------ Total states run: 8 Total run time: 511.510 ms ``` Näyttäisi siltä, että portti 199 on generoitu uudeksi SSH daemonin yhteysportiksi koneelle 'orjakone'. Varmistetaan tietojen oikeellisuus. Tämän voi tehdä etänä SSH-yhteyden avulla muultakin koneelta (testataan yhteyden toimivuus orjakoneen IP:een SSH clientilla porttia 199 käyttäen), mutta tässä varmistamme SSH-yhteyden toimivuuden portissa 199 suoraan minionin näkymästä: /etc/ssh/sshd_config -tiedoston sisältöä SSH-client testauksineen orjakoneen näkymästä ylläolevan ajon jälkeen: ![randomport-from-master](https://raw.githubusercontent.com/Fincer-altego/central-management-of-multiple-servers/master/images/ssh_randomport_for_minion_2.png) Toinen esimerkki: ![randomport-from-master](https://raw.githubusercontent.com/Fincer-altego/central-management-of-multiple-servers/master/images/ssh_randomport_for_minion.png) **Lisänä - SSH-portin vaihtamisen estäminen, jos SSH-yhteyksiä on muodostettu minionille** Jos SSH-yhteyksiä on minionilla auki, voimme haluta estää portin vaihtamisen kesken kaiken. Yllä olevassa SLS-tiedostossa tämä on määritetty state:lla _prevent_if_ssh_sessions_open_. Masterin output, jos minionilla on SSH-yhteyksiä auki: ``` orjakone: ---------- ID: check_sshd_install Function: pkg.installed Result: True Comment: All specified packages are already installed Started: 11:10:01.571133 Duration: 480.26 ms Changes: ---------- ID: check_sshd_config Function: file.managed Name: /etc/ssh/sshd_config Result: True Comment: File /etc/ssh/sshd_config exists with proper permissions. No changes made. Started: 11:10:02.053906 Duration: 1.192 ms Changes: ---------- ID: check_sshd_current_port Function: cmd.run Name: echo "current SSH daemon port for $(hostname) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)" Result: True Comment: Command "echo "current SSH daemon port for $(hostname) is: $(grep -E ^[#P]+ort /etc/ssh/sshd_config)"" run Started: 11:10:02.055645 Duration: 4.458 ms Changes: ---------- pid: 2783 retcode: 0 stderr: stdout: current SSH daemon port for minion is: Port 98 ---------- ID: prevent_if_ssh_sessions_open Function: cmd.run Name: SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi Result: False Comment: Command "SSH_SESSIONS=$(/bin/netstat -ntpa | grep "ESTABLISHED.*sshd"); if [ $(echo $SSH_SESSIONS | wc -w) -gt 1 ]; then echo -e "$(hostname): The following established SSH session were found:\n$SSH_SESSIONS\n\nNot changing SSH daemon port." && false; fi" run Started: 11:10:02.060527 Duration: 12.857 ms Changes: ---------- pid: 2786 retcode: 1 stderr: stdout: -e minion: The following established SSH session were found: tcp6 0 0 ::1:98 ::1:46718 ESTABLISHED 1945/sshd: fincer [ Not changing SSH daemon port. ---------- ID: prevent_if_ssh_sessions_open Function: cmd.run Name: unset SSH_SESSIONS Result: True Comment: Command "unset SSH_SESSIONS" run Started: 11:10:02.073603 Duration: 3.746 ms Changes: ---------- pid: 2794 retcode: 0 stderr: stdout: ---------- ID: ssh_port Function: cmd.run Name: sed -i -r "s/^[#P]+ort [0-9][0-9]*/Port 428/" /etc/ssh/sshd_config Result: False Comment: One or more requisite failed: ssh_random.prevent_if_ssh_sessions_open Changes: ---------- ID: sshd_restart Function: service.running Name: ssh.service Result: False Comment: One or more requisite failed: ssh_random.ssh_port Changes: ---------- ID: ssh_new_port_inform Function: cmd.run Name: echo "new SSH daemon port for $(hostname) is 428" Result: False Comment: One or more requisite failed: ssh_random.sshd_restart, ssh_random.ssh_port Changes: Summary for orjakone ------------ Succeeded: 4 (changed=3) Failed: 4 ------------ Total states run: 8 Total run time: 502.513 ms ``` ![prevent-ssh-portchange_](https://raw.githubusercontent.com/Fincer-altego/central-management-of-multiple-servers/master/images/ssh_prevent_portchange_.png) **e)** Kokeile jonkun toisen opiskelijan tekemää Salt-tilaa. Kokeiltava tila voi olla mistä vain harjoituksesta. Opiskelijoiden raportteja ja koodeja löydät tämän sivun perästä kommenteista. -------------- **Vastaus:** Valitaan henkilön Oliver Siren harjoitus 3:n [Salt state, Jinja for-in loop](https://github.com/Oliver-Siren/palvelinten-hallinta-ict4tn022-4/blob/master/assignments/h3.md#salt-state-jinja-for-in-loop) -tehtävän vastaus. Ladataan wget-komennolla init.sls-tiedosto masterilla paikalliseen kansioon _/srv/salt/student_sample_: SLS-tiedostossa on oletettu, että tiedosto _/srv/salt/jinja/fool.txt_ on olemassa masterilla. Koska sitä ei ole, me luomme sen alla olevassa komentorimpsussa. ``` sudo -- sh -c ' \ mkdir -p /srv/salt/student_sample && mkdir -p /srv/salt/jinja && \ wget https://raw.githubusercontent.com/Oliver-Siren/palvelinten-hallinta-ict4tn022-4/master/assignments/h3.md -O /srv/salt/student_sample/init.sls && \ sed -i '51,61!d' /srv/salt/student_sample/init.sls && \ echo "This is your {{ file }}" > /srv/salt/jinja/fool.txt ' ``` Ajetaan tila masterilta kaikille saataville orja-alkuisille minioneille: ``` sudo salt 'orja*' state.apply student_sample ``` Masterilla saatu output: ``` orjakone: ---------- ID: /tmp/fool/first.txt Function: file.managed Result: True Comment: File /tmp/fool/first.txt updated Started: 00:16:20.842493 Duration: 25.759 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: /tmp/fool/second.txt Function: file.managed Result: True Comment: File /tmp/fool/second.txt updated Started: 00:16:20.868344 Duration: 19.281 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: /tmp/fool/third.txt Function: file.managed Result: True Comment: File /tmp/fool/third.txt updated Started: 00:16:20.887697 Duration: 17.221 ms Changes: ---------- diff: New file mode: 0644 ---------- ID: /tmp/fool/fourth.txt Function: file.managed Result: True Comment: File /tmp/fool/fourth.txt updated Started: 00:16:20.904989 Duration: 19.971 ms Changes: ---------- diff: New file mode: 0644 Summary for orjakone ------------ Succeeded: 4 (changed=4) Failed: 0 ------------ Total states run: 4 Total run time: 82.232 ms ``` Wget:llä ladatun ja sed:llä parsitun esimerkki-SLS -tiedoston sisältö: ``` {% for tiedosto in ['first.txt', 'second.txt', 'third.txt', 'fourth.txt'] %} /tmp/fool/{{ tiedosto }}: file.managed: - source: salt://jinja/fool.txt - makedirs: True - template: jinja - context: file: {{ tiedosto }} {% endfor %} ```