View Controller Scene

screen-shot-2016-11-25-at-10-06-33

developer向けサイト:https://developer.apple.com
developerプログラム:https://developer.apple.com/programs/jp/

ctrl で、support editorにひも付けて、変数myLableにchnageLabelしています。


    @IBOutlet weak var myLabel: UILabel!

    @IBAction func changeLabel(sender: AnyObject) {
        myLabel.text = "You changed me"
    }

tips
command + 0 ->navigator area削除
auto size, auto layout on
story board -> assistant editor -> preview
upgrade frames ->制約に自動調整, items new constrainsで作成時につけることも可能
clear constrains ->制約を解除

上下左右幅いっぱいにするには margin 0
screen-shot-2016-11-25-at-11-15-42
constrain: Editor -> pin -> height or width
view ctrl + dragでも可能
viewを2つ選択して equal height
multiplier: 2つのviewの比率を設定
screen-shot-2016-11-25-at-11-28-09

labelなどのtextはxcode側でサイズを自動計算するので、必ずしも指定しなくてOK
content Hugging priority 大きくなりにくさ

deviceごとに表示を変えるには、画面下のsize classで設定

Electron packager

名言は配列で持たせて、Math.floor(Math.random() * quotes.length)で表示。background-colorは、classを、ipc通信でindex.js, index.html, setting.html間をやりとりしています。また、初期値は、webstorageから値を取得することで、ipc通信を省略しています。

electron document:http://electron.atom.io/docs/

index.js

'use strict';

// index.js (main process)
// -GUI(renderer process)
// -GUI(renderer process)
// -GUI(renderer process)

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const Menu = electron.Menu;
const dialog = electron.dialog;
const ipcMain = electron.ipcMain;

let mainWindow;
let settingsWindow;
// let backgroundColor = 'skyblue';


let menuTemplate = [{
  label: 'MyApp',
  submenu: [
  { label: 'About', accelerator: 'CmdOrCtrl+Shift+A', click:
  function(){ showAboutDialog(); }},
  { type: 'separator'},
  { label: 'Settings', accelerator: 'CmdOrCtrl+,', click:
  function(){ showSettingsWindow(); }},
  { label: 'separator'},
  { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click:
  function(){ app.quit(); }},
  ]

}];
let menu = Menu.buildFromTemplate(menuTemplate);

ipcMain.on('settings_changed', function(event, color){
  mainWindow.webContents.send('set_bgcolor', color);
});


// ipcMain.on('bgcolor_changed', function(event, color){
//   backgroundColor = color;
// });

// ipcMain.on('get_bgcolor', function(event){
//  event.returnValue = backgroundColor;
// });


function showAboutDialog(){
  dialog.showMessageBox({
    type: 'info',
    buttons: ['OK'],
    message: 'About This App',
    detail: 'This app was created by @hpscript'
  });
}
function showSettingsWindow (){
  settingsWindow = new BrowserWindow({width: 600, height: 400});
  settingsWindow.loadURL('file://' + __dirname + '/settings.html');
  // settingsWindow.webContents.openDevTools();
  settingsWindow.show();
  settingsWindow.on('closed', function(){
    settingsWindow = null;
  });
}

function createMainWindow (){
  Menu.setApplicationMenu(menu);
  mainWindow = new BrowserWindow({width: 600, height: 400});
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  // mainWindow.webContents.openDevTools();
  mainWindow.on('closed', function(){
    mainWindow = null;
  });
}

app.on('ready', function(){
 createMainWindow()
});

app.on('window-all-closed', function(){
 if (process.platform !== 'darwin'){
  app.quit();
 }
});

app.on('activate', function(){
  if(mainWindow === null ){
    createMainWindow();
  }
});

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Quotes!</title>
	<style>
	body{
		font-family: Verdana, sans-serif;
		padding: 10px;
		background: skyblue;
	}
	p {
		color: #fff;
		font-size: 36px;
		margin: 0;
		padding: 0;
	}
	</style>
</head>
<body>
	<p id="quote">Just do it!</p>
	<script>
	'use strict';

	const electron = require('electron');
    const ipcRenderer = electron.ipcRenderer;
    const remote = electron.remote;
    const Menu = remote.Menu;
    const MenuItem = remote.MenuItem;
    const shell = remote.shell;

    let color = localStorage.getItem('color') ?
    localStorage.getItem('color') : 'skyblue';
    setBackgroundColor(color);

    let menu = new Menu();
    menu.append(new MenuItem({ label: 'Skyblue', click: function(){
    	setBackgroundColor('skyblue');
    }}));
    menu.append(new MenuItem({ label: 'Tomato', click: function(){
    	setBackgroundColor('tomato');
    }}));
    menu.append(new MenuItem({ label: 'Slate Gray', click: function(){
    	setBackgroundColor('slategray');
    }}));
    window.addEventListener('contextmenu', function(e){
    	e.preventDefault();
    	menu.popup(remote.getCurrentWindow());
    });

    function setBackgroundColor(color){
    	document.body.style.backgroundColor = color;
    	localStorage.setItem('color', color);
    	// ipcRenderer.send('bgcolor_changed', color);
    }

	const quote = document.getElementById('quote');
	const quotes = [
	'Just do it!',
	'Done is better than perfect',
	'Stay hungry, stay foolish',
	'ask, do not tell',
	'focus on the user',
	'keep trying',
	'nothing is impossible',
	'that which is measured, improves',
	];
	window.addEventListener('click', function(){
		quote.innerHTML = quotes[Math.floor(Math.random() * quotes.length)];
	});

	ipcRenderer.on('set_bgcolor', function(event, color){
		setBackgroundColor(color);
	});

	setTimeout(function(){
		let notification = new Notification(
		'Quote!',
		{ body: 'Visit our website!' }
		);
	notification.onclick = function (){
			shell.openExternal('http://google.com');
	}

	},3000);
	</script>
</body>
</html>

setting.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Settings</title>
	<style>
	body{
		font-family: Verdana, sans-serif;
		padding: 10px;
		background: #eee;
	}
	h1 {
		font-size: 16px;
		margin: 0;
		padding: 0 0 10px 0;
	}
	ul {
		list-style: none;
		padding: 0;
		margin: 0;
	}
	ul > li {
		font-size: 14px;
		padding: 3px 0;
	}

	</style>
</head>
<body>
	<h1>Background Color</h1>
	<ul>
		<li><label><input type="radio" name="colors" value="skyblue">Skyblue</label></li>
		<li><label><input type="radio" name="colors" value="tomato">Tomato</label></li>
		<li><label><input type="radio" name="colors" value="slategray">Slate Gray</label></li>
	</ul>
	<script>
	'use strict';

    const ipcRenderer = require('electron').ipcRenderer;
    // let currentColor = ipcRenderer.sendSync('get_bgcolor');
    let currentColor = localStorage.getItem('color');

	let colors = document.getElementsByName('colors');
	for (let i = 0; i < colors.length; i++){
		if (currentColor === colors&#91;i&#93;.value){
			colors&#91;i&#93;.checked = true;
		}
		colors&#91;i&#93;.addEventListener('change', function(){
			let color = this.value;
			// console.log(color);
			// settings.html -> index.js -> index.html
			// ipc module
			ipcRenderer.send('settings_changed', color);
		});
	}
	</script>
</body>
</html>

Electron

AtomはElectronで作られています。
http://electron.atom.io/

Electronのインストール

> lesson\MyApp>npm init -y
> npm i electron-prebuilt --save-dev

package.jsの編集

{
  "name": "MyApp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "electron index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron-prebuilt": "^1.4.8"
  }
}
'use strict';

// index.js (main process)
// -GUI(renderer process)
// -GUI(renderer process)
// -GUI(renderer process)

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

let mainWindow;

app.on('ready', function(){

  mainWindow = new BrowserWindow({width: 600, height: 400});
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.webContents.openDevTools();
  mainWindow.on('closed', function(){
    mainWindow = null;
  });
});

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Quotes!</title>
	<style>
	body{
		font-family: Verdana, sans-serif;
		padding: 10px;
		background: skyblue;
	}
	p {
		color: #fff;
		font-size: 36px;
		margin: 0;
		padding: 0;
	}
	</style>
</head>
<body>
	<p id="quote">Just do it!</p>
</body>
</html>

electronの起動

> npm start

rake spec

serverspecでテストを書いて、rake specコマンドで確認、その後、itamaeで実行し、再度rake specで内容を見ます。

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

itamae recipe.rb

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end
require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

describe file('/var/www/html/index.html') do
  it { should be_file }
  it { should be_owned_by 'apache' }
  it { should be_grouped_into 'apache' }
  its(:content) { should match /Hello World/ }
end

directory '/home/vagrant/myapp'

Serverspec init

サーバーテストツール
http://serverspec.org/resource_types.html

With Serverspec, you can write RSpec tests for checking your servers are configured correctly.
Serverspec tests your servers’ actual state by executing command locally, via SSH, via WinRM, via Docker API and so on. So you don’t need to install any agent softwares on your servers and can use any configuration management tools, Puppet, Ansible, CFEngine, Itamae and so on.

http://serverspec.org/

vagrant fileをつくり、サーバーを二つ起動します。

  # config.vm.box = "bento/centos-6.7"
  config.vm.define "host" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "host"
    node.vm.network :private_network, ip: "192.168.33.13"
  end
  config.vm.define "web" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "web"
    node.vm.network :private_network, ip: "192.168.33.14"
  end

.ssh/config

Host web
 HostName 192.168.33.14
[vagrant@host ~]$ vi .ssh/config
[vagrant@host ~]$ chmod 600 .ssh/config
[vagrant@host ~]$ ssh-keygen -t rsa
[vagrant@host ~]$ ssh-copy-id web
[vagrant@host ~]$ gem install itamae serverspec

serverspec start

[vagrant@host myproject]$ serverspec-init
Select OS type:

  1) UN*X
  2) Windows

Select number: 1

Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 1

Vagrant instance y/n: n
Input target host name: web
 + spec/
 + spec/web/
 + spec/web/sample_spec.rb
 + spec/spec_helper.rb
 + Rakefile
 + .rspec

/myproject/spec/web/httpd_spec.rd

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

rakeコマンドでテストします。

[vagrant@host myproject]$ rake spec
/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb

Package "httpd"
  should be installed (FAILED - 1)

Failures:

  1) Package "httpd" should be installed
     On host `web'
     Failure/Error: it { should be_installed }
       expected Package "httpd" to be installed
       sudo -p 'Password: ' /bin/sh -c rpm\ -q\ httpd
       package httpd is not installed

     # ./spec/web/httpd_spec.rb:4:in `block (2 levels) in '

Finished in 1.33 seconds (files took 0.64117 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/web/httpd_spec.rb:4 # Package "httpd" should be installed

/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb failed

/coockbook/recipe.rb

package 'httpd'
[vagrant@host myproject]$ itamae ssh -h web cookbooks/recipe.rb
 INFO : Starting Itamae...
 INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb
 INFO :   package[httpd] installed will change from 'false' to 'true'

[vagrant@host myproject]$ rake spec
/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb

Package "httpd"
  should be installed

Finished in 0.62513 seconds (files took 0.37567 seconds to load)
1 example, 0 failures

Itamae

ItamaeはRubyで記述できる軽量なサーバ構成管理ツールです。rubyのgemでインストールします。

https://github.com/itamae-kitchen/itamae

gem install itammae

chefのようなフォルダ構成です。
/cookbook/recipe.rb

package 'tree' do
  action :install
  user 'root'
end

> itamae local recipe.rb

[vagrant@host cookbooks]$ itamae local recipe.rb
 INFO : Starting Itamae...
 INFO : Recipe: /home/vagrant/cookbooks/recipe.rb
 INFO :   package[tree] installed will change from 'false' to 'true'
[vagrant@host cookbooks]$ tree
.
-----€ recipe.rb

Resource Type
https://github.com/itamae-kitchen/itamae/wiki/Resources

httpdのインストール、起動

# package 'httpd' do
#   action :install
# end

package 'httpd'

service 'httpd' do
  action [:start, :enable]
end
[vagrant@host cookbooks]$ itamae ssh -h web recipe.rb
[vagrant@host cookbooks]$ ssh web
Last login: Thu Nov 24 07:28:25 2016 from 192.168.33.11
[vagrant@web ~]$ sudo service httpd status
httpd (pid  2559) is running...
template '/var/www/html/index.html' do
  # source 'emplates/index.html.erb'
  owner 'apache'
  group 'apache'
  variables(msg: 'shhh....')
end
[vagrant@host cookbooks]$ itamae ssh -h web recipe.rb

define

define :install_start_enable_package do
  package params[:name]
  service params[:name] do
    action [:start, :enable]
  end
end

install_start_enable_package 'httpd'

設定ファイルの分割

include_recipe './package_recipe.rb'
include_recipe './service_recipe.rb'

tmux commands

tmux is a terminal multiplexer
What is a terminal multiplexer? It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more.

[vagrant@localhost ~]$ sudo yum -y install tmux
インストール:
  tmux.x86_64 0:1.6-3.el6
完了しました!

tmuxの起動

[vagrant@localhost ~]$ tmux new -s ProjectA

Ctrl+Bがデフォルトのコマンドプレフィックスキー

$ top
$ ctl + b + d 
->[detached]

attach

$tmux a -t ProjectA

session rename

Ctrl+b $

session list

[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]

session delete : tmux kill-serverで全て削除

[vagrant@localhost ~]$ tmux kill-session -t ProjectB
[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]
ProjectC: 1 windows (created Thu Nov 24 13:51:07 2016) [80x23]

ctl + b + ? コマンドキー一覧表示
ctl + b + : コマンドライン表示
ctl + b + t 時計モード

ctl + b + c 新しいwindow(bash)の起動、 ctl + b + 番号、もしくは、n(next), p(previous)でwindow変更
ctl + b + . window名をつける
ctl + b + w window一覧
ctl + b + f window検索
ctl + b + & window削除

ctl + b + ” 水平分割
ctl + b + % 横分割
ctl + b + o pane移動
ctl + b + q 番号指定で移動
clt + b + {} paneの位置移動
ctl + b + x paneの解除
ctl + b + ! windowを開く

paneのサイズ変更
ctl + b : -> :resize-pane -U 5

vi ~/.tmux.conf ファイルにショートカットキーの設定、prefix keyも変更可

set -g C-t
unbind C-b
bind C-t send-prefix \; display "configuration reloaded"

bind r source-file ~/.tmux.conf 

set -g mode-keys vi

bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

new THREE.Scene();

%e7%84%a1%e9%a1%8c

%e7%84%a1%e9%a1%8c

%e7%84%a1%e9%a1%8c

three.jsで作成しまています。なにかunityと似てると思ったら、WebGLという技術ですね。

https://threejs.org/

reference
WebGL (Web Graphics Library) is a JavaScript API for rendering interactive 3D computer graphics and 2D graphics within any compatible web browser without the use of plug-ins.

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>threejs</title>
</head>
<body>
	<div id="stage"></div>
  <script src="js/three.min.js"></script>
  <script src="js/OrbitControls.js"></script>
  <script>
  (function(){
    'use strict'

    var scene;
    var person;
    var head;
    var body;
    var box;
    var sphere1;
    var sphere2;
    var sphere3;
    var plane;
    var light;
    var ambient;
    var camera;
    var gridHelper;
    var axisHelper;
    var lightHelper;
    var renderer;
    var width = 500;
    var height = 250;
    var controls;
    var theta = 0;
    var shadowHelper;
  // scene stage
    scene = new THREE.Scene();

  // mesh -geometry, material
    box = new THREE.Mesh(
      new THREE.BoxGeometry(20, 20, 20),
      new THREE.MeshLambertMaterial({
        color: new THREE.Color(0xff0000)})
    );
    box.position.set(0, 0, 0);
    scene.add(box);

    plane = new THREE.Mesh(
      new THREE.PlaneGeometry(200, 200),
      new THREE.MeshLambertMaterial({
        color: new THREE.Color(0x0096d6), side: THREE.DoubleSide})
    );
    plane.position.set(0, -50, 0);
    plane.rotation.x = 90 * Math.PI/180;
    scene.add(plane);


    // light
    light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 100, 30);
    scene.add(light);
    // ambient
    ambient = new THREE.AmbientLight(0x404040);
    scene.add(ambient);

  // camera
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
    camera.position.set(200, 100, 300);
    camera.lookAt(scene.position);

    // helper
    gridHelper = new THREE.GridHelper(200, 50);
    scene.add(gridHelper);
    axisHelper = new THREE.AxisHelper(1000);
    scene.add(axisHelper);
    lightHelper = new THREE.DirectionalLightHelper(light, 20);
    scene.add(lightHelper);

    // controls
    controls = new THREE.OrbitControls(camera);
    // controls.autoRotate = true;

  // render
  renderer = new THREE.WebGLRenderer({ antialias: true});
  renderer.setSize(width, height);
  renderer.setClearColor(0xefefef);
  renderer.setPixelRatio(window.devicePixelRatio);
  document.getElementById('stage').appendChild(renderer.domElement);

  // shadow
  renderer.shadowMap.enabled = true;
  light.castShadow = true;
  light.shadow.camera.left = -200;
  light.shadow.camera.right = 200;
  light.shadow.camera.top = 200;
  light.shadow.camera.bottom = -200;
  shadowHelper = new THREE.CameraHelper(light.shadow.camera);
  scene.add(shadowHelper);
  box.castShadow = true;
  plane.receiveShadow = true;

  function render(){
    requestAnimationFrame(render);

    controls.update();
    renderer.render(scene, camera);
  }
  render();

  })();
  </script>
</body>
</html>

playbookによるapache起動

---
- hosts: all
  sudo: yes
  tasks:
    - name: add a new user
      user: name=sakura

- hosts: web
  sudo: yes
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: start apache and enabled
      service: name=httpd state=started enabled=yes
[vagrant@host ~]$ vi playbook.yml
[vagrant@host ~]$ ansible-playbook playbook.yml
---
- hosts: all
  sudo: yes
  tasks:
    - name: add a new user
      user: name=sakura
    - name: install libselinux-python
      yum: name=libselinux-python state=latest

- hosts: web
  sudo: yes
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: start apache and enabled
      service: name=httpd state=started enabled=yes
    - name: change owner
      file: dest=/var/www/html owner=vagrant recurse=yes
    - name: copy index.html
      copy: src=./index.html dest=/var/www/html/index.html owner=vagrant

playbook.yml

---
- hosts: all
  sudo: yes
  tasks:
    - name: add a new user
      user: name=sakura
    - name: install libselinux-python
      yum: name=libselinux-python state=latest

- hosts: web
  sudo: yes
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: start apache and enabled
      service: name=httpd state=started enabled=yes
    - name: change owner
      file: dest=/var/www/html owner=vagrant recurse=yes
    - name: copy index.html
      copy: src=./index.html dest=/var/www/html/index.html owner=vagrant
    - name: install php packages
      yum: name={{item}} state=latest
      with_items:
       - php
       - php-devel
       - php-mbstring
       - php-mysql
      notify:
       - restart apache
    - name: copy hello.php
      copy: src=./hello.php dest=/var/www/html/hello.php owner=vagrant
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

- hosts: db
  sudo: yes
  tasks:
    - name: install mysql
      yum: name=mysql-server state=latest
    - name: start mysql and enabled
      service: name=mysqld state=started enabled=yes
    - name: create a database
      mysql_db: name=db state=present
    - name: create a user for mydb
      mysql_user: name=dbuser password=dbpassword priv=mydb.*:All state=present

playbook.yml

hostでplaybookを作成します。

[vagrant@host ~]$ vi playbook.yml
---
 hosts: all
 sudo: yes
 tasks:
  - name: add a new user
    user: name=sakura

playbookを実行します。

[vagrant@host ~]$ ansible-playbook playbook.yml
[DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and make sure
become_method is 'sudo' (default).
This feature will be removed in a future release.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [192.168.43.52]
ok: [192.168.43.53]

TASK [add a new user] **********************************************************
changed: [192.168.43.53]
changed: [192.168.43.52]

PLAY RECAP *********************************************************************
192.168.43.52              : ok=2    changed=1    unreachable=0    failed=0
192.168.43.53              : ok=2    changed=1    unreachable=0    failed=0

ansible-playbook playbook.yml –syntax-check
ansible-playbook playbook.yml –check