├── README.md ├── SUMMARY.md ├── _book ├── doc │ ├── hosts.html │ ├── introduction.html │ ├── modeul.html │ └── playbook.html ├── gitbook │ ├── fonts │ │ └── fontawesome │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ ├── gitbook-plugin-fontsettings │ │ ├── fontsettings.js │ │ └── website.css │ ├── gitbook-plugin-highlight │ │ ├── ebook.css │ │ └── website.css │ ├── gitbook-plugin-livereload │ │ └── plugin.js │ ├── gitbook-plugin-lunr │ │ ├── lunr.min.js │ │ └── search-lunr.js │ ├── gitbook-plugin-search │ │ ├── lunr.min.js │ │ ├── search-engine.js │ │ ├── search.css │ │ └── search.js │ ├── gitbook-plugin-sharing │ │ └── buttons.js │ ├── gitbook.js │ ├── images │ │ ├── apple-touch-icon-precomposed-152.png │ │ └── favicon.ico │ ├── style.css │ └── theme.js ├── index.html ├── res │ ├── ansible.cfg │ ├── echo.retry │ ├── echo.yml │ ├── golang │ │ ├── hello.go │ │ └── write.go │ ├── helloworld.retry │ ├── helloworld.yml │ ├── library │ │ ├── hello │ │ └── write │ ├── loop.yml │ ├── preferences.fact │ ├── when.retry │ ├── when.yml │ └── write.yml └── search_index.json ├── doc ├── config.md ├── hosts.md ├── introduction.md ├── modeul.md └── playbook.md └── res ├── ansible.cfg ├── echo.yml ├── golang ├── fuck.go ├── hello.go └── write.go ├── helloworld.yml ├── host ├── library ├── fuck ├── hello └── write ├── loop.yml ├── preferences.fact ├── when.yml └── write.yml /README.md: -------------------------------------------------------------------------------- 1 | # Ansible 2 | 这个项目讲述了Ansible的基本使用方法,和开发自定义模块的方式和例子 3 | # 目录 4 | * [Ansible简介](./doc/introduction.md#desc) 5 | * [Ansible的特点](./doc/introduction.md#tedian) 6 | * [Hello World](./doc/introduction.md#helloworld) 7 | * [安装方式](./doc/introduction.md#anzhuang) 8 | * [Hosts文件](./doc/hosts.md#hosts) 9 | * [编写host文件](./doc/hosts.md#xiehosts) 10 | * [playbook](./doc/playbook.md#playbook) 11 | * [helloworld](./doc/playbook.md#helloworld) 12 | * [变量](./doc/playbook.md#bianliang) 13 | * [条件](./doc/playbook.md#tiaojian) 14 | * [自定义模块](./doc/modeul.md#modeul) 15 | * [参数](./doc/modeul.md#canshu) 16 | * [返回值](./doc/modeul.md#fanhuizhi) 17 | * [使用自定义模块](./doc/modeul.md#shiyon) 18 | * [Ansible配置](./doc/config.md) 19 | 20 | # demo 21 | 这里编写一个名字叫做`fuck`的模块,他的功能是往标准输出里面输出`fuck`. 22 | ```golang 23 | package main 24 | 25 | import ( 26 | "encoding/json" 27 | ) 28 | 29 | // Response 返回值的消息结构 30 | type Response struct { 31 | Changed bool `json:"changed"` 32 | Fail bool `json:"fail"` 33 | Msg string `json:"msg"` 34 | RC int `json:"rc"` 35 | } 36 | 37 | func main() { 38 | println("fuck") 39 | var res = Response{ 40 | Changed: false, 41 | Fail: false, 42 | Msg: "", 43 | RC: 0, 44 | } 45 | buf, _ := json.Marshal(res) 46 | println(string(buf)) 47 | } 48 | ``` 49 | 编译之后放在模块的目录中 50 | ```shell 51 | mac-pro:res jukay$ ansible dev -m fuck -u root 52 | 39.106.10.228 | SUCCESS => { 53 | "changed": false, 54 | "fail": false, 55 | "msg": "", 56 | "rc": 0 57 | } 58 | mac-pro:res jukay$ 59 | ``` -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | 2 | * [ 目录](./README.md) 3 | 4 | * [Ansible简介](./doc/introduction.md#desc) 5 | * [Ansible的特点](./doc/introduction.md#tedian) 6 | * [Hello World](./doc/introduction.md#helloworld) 7 | * [安装方式](./doc/introduction.md#anzhuang) 8 | * [Hosts文件](./doc/hosts.md#hosts) 9 | * [编写host文件](./doc/hosts.md#xiehosts) 10 | * [playbook](./doc/playbook.md#playbook) 11 | * [helloworld](./doc/playbook.md#helloworld) 12 | * [变量](./doc/playbook.md#bianliang) 13 | * [条件](./doc/playbook.md#tiaojian) 14 | * [自定义模块](./doc/modeul.md#modeul) 15 | * [参数](./doc/modeul.md#canshu) 16 | * [返回值](./doc/modeul.md#fanhuizhi) 17 | * [使用自定义模块](./doc/modeul.md#shiyon) 18 | * [Ansible配置](./doc/config.md) -------------------------------------------------------------------------------- /_book/doc/hosts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hosts文件 · GitBook 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
70 |
71 | 72 | 73 | 76 | 77 | 78 | 325 | 326 | 327 |
328 | 329 |
330 | 331 |
332 | 333 | 334 | 335 | 344 | 345 | 346 | 347 | 348 |
349 |
350 | 351 |
352 |
353 | 354 |
355 | 356 |

Hosts文件介绍

357 |

    Anasible管理者海量的机器,这些机器的ip和用户密码都配置在Ansible的hosts文件中,hosts文件默认是存在/etc/ansible/hosts这个地址,也是可以在运行过程中指定的,比如

358 |
bash-3.2$ ansible huanggai -m command -a "echo hello world" -v -i /Users/jukay/Desktop/hosts
359 | No config file found; using defaults
360 | huanggai | SUCCESS | rc=0 >>
361 | hello world
362 | 
363 |

编写host文件

364 |

    Ansible的hosts文件格式如下:

365 |

366 | [test]
367 | aliyun       ansible_host=47.92.102.184 ansible_user=root ansible_ssh_private_key_file=~/.ssh/aliyun
368 | huanggai        ansible_host=192.168.1.197 ansible_user=deploy ansible_ssh_port=9122
369 | 
370 | [defualt]
371 | ansible_ssh_private_key_file=~/.ssh/aliyun
372 | baochai      ansible_host=192.168.1.191 ansible_user=deploy ansible_ssh_port=9122
373 | daiyu        ansible_host=192.168.1.192 ansible_user=deploy ansible_ssh_port=9122
374 | xiangyun     ansible_host=192.168.1.193 ansible_user=deploy ansible_ssh_port=9122
375 | xifeng       ansible_host=192.168.1.195 ansible_user=deploy ansible_ssh_port=9122
376 | xiren        ansible_host=192.168.1.196 ansible_user=deploy ansible_ssh_port=9122
377 | huanggai        ansible_host=192.168.1.197 ansible_user=deploy ansible_ssh_port=9122
378 | yuanchun     ansible_host=192.168.1.224 ansible_user=deploy ansible_ssh_port=9122
379 | puppetmaster ansible_host=192.168.1.224 ansible_user=deploy ansible_ssh_port=9122
380 | hp           ansible_host=192.168.1.225 ansible_user=deploy ansible_ssh_port=9122
381 | jira         ansible_host=192.168.1.227 ansible_user=deploy ansible_ssh_port=9122
382 | caiyun       ansible_host=192.168.1.234 ansible_user=deploy ansible_ssh_port=9122
383 | caohong      ansible_host=192.168.2.49 ansible_user=deploy ansible_ssh_port=9122
384 | caozhi       ansible_host=192.168.2.50 ansible_user=deploy ansible_ssh_port=9122
385 | caopi        ansible_host=192.168.2.51 ansible_user=deploy ansible_ssh_port=9122
386 | caochong     ansible_host=192.168.2.52 ansible_user=deploy ansible_ssh_port=9122
387 | ceshi        ansible_host=47.92.102.184 ansible_user=deploy ansible_ssh_port=9122
388 | 
389 |

[test]是什么意思?

390 |
391 |

[test]表示对机器进行了分组,这里aliyun和huanggai作为一组机器,组的名字叫test,其他机器座位一组,名字叫defualt,我们可以直接对着一组机器进操作,比如,我们直接调用ping模块来查看一组机器的网络情况

392 |
bash-3.2$  ansible test -m  ping -v -i /Users/jukay/Desktop/hosts
393 | No config file found; using defaults
394 | huanggai | SUCCESS => {
395 |     "changed": false,
396 |     "ping": "pong"
397 | }
398 | aliyun | SUCCESS => {
399 |     "changed": false,
400 |     "ping": "pong"
401 | }
402 | 
403 |

我们也可以一组机器加若干台机器一起执行命令

404 |
bash-3.2$  ansible test,daiyu -m  ping -v -i /Users/jukay/Desktop/hosts
405 | No config file found; using defaults
406 | daiyu | UNREACHABLE! => {
407 |     "changed": false,
408 |     "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n",
409 |     "unreachable": true
410 | }
411 | huanggai | SUCCESS => {
412 |     "changed": false,
413 |     "ping": "pong"
414 | }
415 | aliyun | SUCCESS => {
416 |     "changed": false,
417 |     "ping": "pong"
418 | }
419 | 
420 |
421 |

ansible_host是什么意思?

422 |
423 |

ansible_host表示目标机器的ip地址.如果这个地址如当前网络不通,那么ansible命令会返回UNREACHABLE!

424 |
425 |

ansible_user是什么意思?

426 |
427 |

ansible_user表示登录到目标机器时候使用的用户账号。

428 |
429 |

ansible_ssh_port是什么意思?

430 |
431 |

ansible_ssh_port是ansible通过ssh连接到目标机器时候使用的端口,默认是22号端口。

432 |
433 | 434 | 435 |
436 | 437 |
438 |
439 |
440 | 441 |

results matching ""

442 |
    443 | 444 |
    445 |
    446 | 447 |

    No results matching ""

    448 | 449 |
    450 |
    451 |
    452 | 453 |
    454 |
    455 | 456 |
    457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 |
    472 | 473 | 479 |
    480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | -------------------------------------------------------------------------------- /_book/doc/introduction.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Ansible简介 · GitBook 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
    70 |
    71 | 72 | 73 | 76 | 77 | 78 | 325 | 326 | 327 |
    328 | 329 |
    330 | 331 |
    332 | 333 | 334 | 335 | 344 | 345 | 346 | 347 | 348 |
    349 |
    350 | 351 |
    352 |
    353 | 354 |
    355 | 356 |

    Ansible简介

    357 |

        Ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

    358 |

    Ansible的特点

    359 |

        Ansible是基于模块工作的,ansible本身是没有批量部署的能力,他只是提供了服务端通信功能,模块执行功能,以及一些核心的模块。还有一个比较特别的地方是:Ansible是不要安装客户端的,他只要求目标机器上安装了Python2.4以及以上版本即可。同时Ansible也是支持windows的.

    360 |

    HelloWorld

    361 |
     ~/C/M/ansible  ansible huanggai -m command -a "echo hello world"                                                             1009ms  六  9/30 13:39:21 2017
    362 | huanggai | SUCCESS | rc=0 >>
    363 | hello world
    364 | 
    365 |

    解释说明:huanggai 是指配置在/etc/ansible/hosts文件中的机器, -m 表示选择模块 command是Ansible的内置模块,-a表示的是command模块的参数

    366 |

    安装Ansible

    367 |
      368 |
    • mac:
      369 | brew install ansible
    • 370 |
    • centos:
      371 | yum install ansible
    • 372 |
    • ubuntu:
      373 | apt-get install ansible
    • 374 |
    375 | 376 | 377 |
    378 | 379 |
    380 |
    381 |
    382 | 383 |

    results matching ""

    384 |
      385 | 386 |
      387 |
      388 | 389 |

      No results matching ""

      390 | 391 |
      392 |
      393 |
      394 | 395 |
      396 |
      397 | 398 |
      399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 |
      414 | 415 | 421 |
      422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | -------------------------------------------------------------------------------- /_book/doc/modeul.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 自定义模块 · GitBook 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
      70 |
      71 | 72 | 73 | 76 | 77 | 78 | 325 | 326 | 327 |
      328 | 329 |
      330 | 331 |
      332 | 333 | 334 | 335 | 344 | 345 | 346 | 347 | 348 |
      349 |
      350 | 351 |
      352 |
      353 | 354 |
      355 | 356 |

      自定义模块

      357 |

      有时候官方自带的模块不能完成我们需要的功能,或者实现起来非常复杂的时候,这个时候我们也找不到开源的已有方案,我们可以考虑自己编写Ansible模块,他的使用方法和核心模块的使用方法是一样的。Ansible在设计的是并没有限制我们开发Ansible模块时候使用的语言。Ansible在2.2以后就支持二进制模块了,所以我们可以使用golang来编写Ansible模块。

      358 |

      首先,将模块文件读入内存,然后添加传递给模块的参数,最后将模块中所需要的类添加到内存,由zipfile压缩后,再由base64进行编码,写入到模版文件内。

      359 |

      通过默认的连接方式,一般是ssh。ansible通过ssh连接到远程主机,创建临时目录,并关闭连接。然后将打开另外一个ssh连接,将模版文件以sftp方式传送到刚刚创建的临时目录中,写完后关闭连接。然后打开一个ssh连接将任务对象赋予可执行权限,执行成功后关闭连接。

      360 |

      最后,ansible将打开第三个连接来执行模块,并删除临时目录及其所有内容。模块的结果是从标准输出stdout中获取json格式的字符串。ansible将解析和处理此字符串。如果有任务是异步控制执行的,ansible将在模块完成之前关闭第三个连接,并且返回主机后,在规定的时间内检查任务状态,直到模块完成或规定的时间超时。

      361 |

      读取参数

      362 |

      我们在使用golang开发模块的时候,面临一个问题:如何读取Ansible的参数?Ansible是将参数以json的形式写入到一个临时文件中,然后将这个临时文件的路径传给golang的命令行,我们可以用os.Args[1]来获取这个json文件。读取参数成功以后,我们就可以使用golang在目标机器上执行命令或者操作文件和网络等等。

      363 |
      package main
      364 | 
      365 | import (
      366 |     "encoding/json"
      367 |     "fmt"
      368 |     "io/ioutil"
      369 |     "os"
      370 | )
      371 | 
      372 | // Response 返回值
      373 | type Response struct {
      374 |     Changed bool   `json:"changed"`
      375 |     Fail    bool   `json:"fail"`
      376 |     Msg     string `json:"msg"`
      377 |     RC      int    `json:"rc"`
      378 | }
      379 | 
      380 | func main() {
      381 |     var args = os.Args[:]
      382 |     var response Response
      383 |     if len(args) != 2 {
      384 |         response.Fail = true
      385 |         response.Msg = "失败"
      386 |         response.Changed = false
      387 |     }
      388 |     contents, err := readJSON(args[1])
      389 |     if err != nil {
      390 |         response.Msg = err.Error()
      391 |         response.Fail = true
      392 |         response.Changed = false
      393 | 
      394 |     } else {
      395 |         var m = make(map[string]string)
      396 |         json.Unmarshal([]byte(contents), &m)
      397 |         response.Msg = " Hello " + m["name"]
      398 |         response.Fail = false
      399 |         response.Changed = false
      400 |     }
      401 | 
      402 |     buffer, _ := json.Marshal(response)
      403 |     fmt.Println(string(buffer))
      404 | }
      405 | 
      406 | func readJSON(f string) (string, error) {
      407 |     fh, err := os.Open(f)
      408 |     if err != nil {
      409 |         return "", err
      410 |     }
      411 |     contents, err := ioutil.ReadAll(fh)
      412 |     return string(contents), err
      413 | }
      414 | 
      415 |

      返回值

      416 |

      Ansible的返回值是一个json,他一般可能包括以下几个部分。

      417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 |
      字段类型说明
      backup_filestring对于一些modules使用了backup变量,返回备份的文件路径
      changedbool表示任务是否对服务器进行了修改
      failedbool表示任务是否失败
      invocationmap调用模块的方法
      msgstring返回的消息
      rcint命令行程序的返回码
      resultsmap如果该键存在,则表示该任务存在循环,并且它包含每个项目的模块“results”的列表
      skippedbool是否跳过执行
      stderrstring标准错误输出
      stderr_lineslist它将stderr字符串按行分割存储在列表中
      stdoutstring标准输出
      stdout_lineslist它将stdout字符串按行分割存储在列表中
      488 |

      如何使用自己写的模块

      489 |

      自动以的模块的使用方法和核心模块的使用方法基本是一致的,这里举个例子

      490 |
      ---
      491 | - name:
      492 |   hosts: aliyun
      493 |   remote_user: root
      494 |   tasks:
      495 |   - name: Hello World版本的playbook
      496 |     hello:
      497 |       name: "{{ item }}"
      498 |     with_items: ["licong",caobo]
      499 | 
      500 |

      这里的hello就是上面的自定义模块,当然,我们也可以item参数改成从ansible参数传递一进去的形式。 501 | 使用golang开发Ansible模块的弊端就是无法跨平台,而python是可以跨平台执行的,而且golang在编译以后,二进制包的体积比较大,python开发的模块一般只有几kb大小。

      502 | 503 | 504 |
      505 | 506 |
      507 |
      508 |
      509 | 510 |

      results matching ""

      511 |
        512 | 513 |
        514 |
        515 | 516 |

        No results matching ""

        517 | 518 |
        519 |
        520 |
        521 | 522 |
        523 |
        524 | 525 |
        526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 |
        541 | 542 | 548 |
        549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | -------------------------------------------------------------------------------- /_book/doc/playbook.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | playbook · GitBook 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
        70 |
        71 | 72 | 73 | 76 | 77 | 78 | 325 | 326 | 327 |
        328 | 329 |
        330 | 331 |
        332 | 333 | 334 | 335 | 344 | 345 | 346 | 347 | 348 |
        349 |
        350 | 351 |
        352 |
        353 | 354 |
        355 | 356 |

        playbook

        357 |

        什么是playbook?

        358 |
        359 |

        Playbooks 的格式是YAML(详见:YAML 语法),语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本,但它也并不是一个配置模型或过程的模型.playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用,这在前面章节学习过.‘plays’ 好似音符,playbook 好似由 ‘plays’ 构成的曲谱,通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 database server 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.“plays” 算是一个体育方面的类比,你可以通过多个 plays 告诉你的系统做不同的事情,不仅是定义一种特定的状态或模型.你可以在不同时间运行不同的 plays.

        360 |
        361 |

        对初学者,这里有一个 playbook,其中仅包含一个 play:

        362 |
        ---
        363 | - hosts: webservers
        364 |   remote_user: root
        365 |   tasks:
        366 |   - name: ensure apache is at the latest version
        367 |     yum: pkg=httpd state=latest
        368 |   - name: write the apache config file
        369 |     template: src=/srv/httpd.j2 dest=/etc/httpd.conf
        370 |     notify:
        371 |     - restart apache
        372 |   - name: ensure apache is running
        373 |     service: name=httpd state=started
        374 |   handlers:
        375 |     - name: restart apache
        376 |       service: name=httpd state=restarted
        377 | 
        378 |

        Hello World

        379 |

        我们来编写一个Hello World版本的playbook

        380 |
        ---
        381 | - hosts: aliyun
        382 |   remote_user: root
        383 |   tasks:
        384 |   - name: Hello World版本的playbook
        385 |     shell: /bin/echo Hello World
        386 | 
        387 |

        变量

        388 |

            上面的例子中,有些东西我们是写死了,不方复用。比如说hosts就可以写成变量形式

        389 |
        ---
        390 | - hosts: {{host}}
        391 |   remote_user: root
        392 |   tasks:
        393 |   - name: Hello World版本的playbook
        394 |     shell: /bin/echo Hello World
        395 | 
        396 |

        这样我们可以在执行过程中,通过命令行参数吧host传进来,也可以吧Host变量的值写当前文件的preferences.fact文件中。

        397 |
        ansible-playbook helloworld.yum -extra-vars="host=aliyun"
        398 | 
        399 |

        这里我们-extra-vars参数传递了host参数到yml文件中,在Ansible的1.2版本以后是支持传json的

        400 |
        –extra-vars ‘{“pacman”:”mrs”,”ghosts”:[“inky”,”pinky”,”clyde”,”sue”]}’
        401 | 
        402 |

        在Ansible的1.3版本以后,可以直接加载一个json文件

        403 |
        –extra-vars “@some_file.json”
        404 | 
        405 |

        条件

        406 |

        Ansible在执行task的时候,是可以按照条件决定是否执行的

        407 |
        ---
        408 | - name: if条件
        409 |   hosts: localhost
        410 |   tasks:
        411 |   - name:
        412 |     shell: echo "Hello World"
        413 |     when: a == '10'
        414 | 
        415 |

        执行

        416 |
         ~/C/M/a/res  ansible-playbook if.yml --extra-vars "a=100" -v                                    1406ms  一 10/ 9 18:38:54 2017
        417 | Using /Users/jukay/Code/Markdown/ansible/res/ansible.cfg as config file
        418 | 
        419 | PLAY [if条件] *********************************************************************************************************************
        420 | 
        421 | TASK [Gathering Facts] **********************************************************************************************************
        422 | ok: [localhost]
        423 | 
        424 | TASK [command] ******************************************************************************************************************
        425 | skipping: [localhost] => {"changed": false, "skip_reason": "Conditional result was False", "skipped": true}
        426 | 
        427 | PLAY RECAP **********************************************************************************************************************
        428 | localhost                  : ok=1    changed=0    unreachable=0    failed=0
        429 | 
        430 |

        这里提示条件不满足,跳过了 431 | 如果换一下参数

        432 |
        Using /Users/jukay/Code/Markdown/ansible/res/ansible.cfg as config file
        433 | 
        434 | PLAY [if条件] *********************************************************************************************************************
        435 | 
        436 | TASK [Gathering Facts] **********************************************************************************************************
        437 | ok: [localhost]
        438 | 
        439 | TASK [command] ******************************************************************************************************************
        440 | changed: [localhost] => {"changed": true, "cmd": "echo \"Hello World\"", "delta": "0:00:00.007619", "end": "2017-10-09 18:41:01.170398", "rc": 0, "start": "2017-10-09 18:41:01.162779", "stderr": "", "stderr_lines": [], "stdout": "Hello World", "stdout_lines": ["Hello World"]}
        441 | 
        442 | PLAY RECAP **********************************************************************************************************************
        443 | localhost                  : ok=2    changed=1    unreachable=0    failed=0
        444 | 
        445 |

        这里标准输出就能成功输出Hello World。类型的条件判断还有

        446 |
          447 |
        • in 判断一个字符串是否存在另外一个字符串中
        • 448 |
        • is define 判断一个变量是否定义
        • 449 |
        • not 判断布尔类型是否为false
        • 450 |
        • a|b 判断两个布尔类型是否至少一个为true
        • 451 |
        • > 或者 < 判断大小关系
        • 452 |
        • or 和 | 一样
        • 453 |
        • 等等。。。
        • 454 |
        455 |

        迭代

        456 |

        Ansible的参数是可以传列表的

        457 |
        ---
        458 | - name: loop
        459 |   hosts: localhost
        460 |   remote_user: jukay
        461 |   tasks:
        462 |   - name: 
        463 |     shell: echo Hello {{item}}
        464 |     with_items: [licong,caobo]
        465 | 
        466 |

        或者

        467 |
        ---
        468 | - name: loop
        469 |   hosts: localhost
        470 |   remote_user: jukay
        471 |   tasks:
        472 |   - name: 
        473 |     shell: echo Hello {{item}}
        474 |     with_items:
        475 |     - licong
        476 |     - caobo
        477 | 
        478 |

        迭代map和object数组都是可以的。

        479 | 480 | 481 |
        482 | 483 |
        484 |
        485 |
        486 | 487 |

        results matching ""

        488 |
          489 | 490 |
          491 |
          492 | 493 |

          No results matching ""

          494 | 495 |
          496 |
          497 |
          498 | 499 |
          500 |
          501 | 502 |
          503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 |
          518 | 519 | 525 |
          526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/fonts/fontawesome/FontAwesome.otf -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js: -------------------------------------------------------------------------------- 1 | require(['gitbook', 'jquery'], function(gitbook, $) { 2 | // Configuration 3 | var MAX_SIZE = 4, 4 | MIN_SIZE = 0, 5 | BUTTON_ID; 6 | 7 | // Current fontsettings state 8 | var fontState; 9 | 10 | // Default themes 11 | var THEMES = [ 12 | { 13 | config: 'white', 14 | text: 'White', 15 | id: 0 16 | }, 17 | { 18 | config: 'sepia', 19 | text: 'Sepia', 20 | id: 1 21 | }, 22 | { 23 | config: 'night', 24 | text: 'Night', 25 | id: 2 26 | } 27 | ]; 28 | 29 | // Default font families 30 | var FAMILIES = [ 31 | { 32 | config: 'serif', 33 | text: 'Serif', 34 | id: 0 35 | }, 36 | { 37 | config: 'sans', 38 | text: 'Sans', 39 | id: 1 40 | } 41 | ]; 42 | 43 | // Return configured themes 44 | function getThemes() { 45 | return THEMES; 46 | } 47 | 48 | // Modify configured themes 49 | function setThemes(themes) { 50 | THEMES = themes; 51 | updateButtons(); 52 | } 53 | 54 | // Return configured font families 55 | function getFamilies() { 56 | return FAMILIES; 57 | } 58 | 59 | // Modify configured font families 60 | function setFamilies(families) { 61 | FAMILIES = families; 62 | updateButtons(); 63 | } 64 | 65 | // Save current font settings 66 | function saveFontSettings() { 67 | gitbook.storage.set('fontState', fontState); 68 | update(); 69 | } 70 | 71 | // Increase font size 72 | function enlargeFontSize(e) { 73 | e.preventDefault(); 74 | if (fontState.size >= MAX_SIZE) return; 75 | 76 | fontState.size++; 77 | saveFontSettings(); 78 | } 79 | 80 | // Decrease font size 81 | function reduceFontSize(e) { 82 | e.preventDefault(); 83 | if (fontState.size <= MIN_SIZE) return; 84 | 85 | fontState.size--; 86 | saveFontSettings(); 87 | } 88 | 89 | // Change font family 90 | function changeFontFamily(configName, e) { 91 | if (e && e instanceof Event) { 92 | e.preventDefault(); 93 | } 94 | 95 | var familyId = getFontFamilyId(configName); 96 | fontState.family = familyId; 97 | saveFontSettings(); 98 | } 99 | 100 | // Change type of color theme 101 | function changeColorTheme(configName, e) { 102 | if (e && e instanceof Event) { 103 | e.preventDefault(); 104 | } 105 | 106 | var $book = gitbook.state.$book; 107 | 108 | // Remove currently applied color theme 109 | if (fontState.theme !== 0) 110 | $book.removeClass('color-theme-'+fontState.theme); 111 | 112 | // Set new color theme 113 | var themeId = getThemeId(configName); 114 | fontState.theme = themeId; 115 | if (fontState.theme !== 0) 116 | $book.addClass('color-theme-'+fontState.theme); 117 | 118 | saveFontSettings(); 119 | } 120 | 121 | // Return the correct id for a font-family config key 122 | // Default to first font-family 123 | function getFontFamilyId(configName) { 124 | // Search for plugin configured font family 125 | var configFamily = $.grep(FAMILIES, function(family) { 126 | return family.config == configName; 127 | })[0]; 128 | // Fallback to default font family 129 | return (!!configFamily)? configFamily.id : 0; 130 | } 131 | 132 | // Return the correct id for a theme config key 133 | // Default to first theme 134 | function getThemeId(configName) { 135 | // Search for plugin configured theme 136 | var configTheme = $.grep(THEMES, function(theme) { 137 | return theme.config == configName; 138 | })[0]; 139 | // Fallback to default theme 140 | return (!!configTheme)? configTheme.id : 0; 141 | } 142 | 143 | function update() { 144 | var $book = gitbook.state.$book; 145 | 146 | $('.font-settings .font-family-list li').removeClass('active'); 147 | $('.font-settings .font-family-list li:nth-child('+(fontState.family+1)+')').addClass('active'); 148 | 149 | $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ''); 150 | $book.addClass('font-size-'+fontState.size); 151 | $book.addClass('font-family-'+fontState.family); 152 | 153 | if(fontState.theme !== 0) { 154 | $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ''); 155 | $book.addClass('color-theme-'+fontState.theme); 156 | } 157 | } 158 | 159 | function init(config) { 160 | // Search for plugin configured font family 161 | var configFamily = getFontFamilyId(config.family), 162 | configTheme = getThemeId(config.theme); 163 | 164 | // Instantiate font state object 165 | fontState = gitbook.storage.get('fontState', { 166 | size: config.size || 2, 167 | family: configFamily, 168 | theme: configTheme 169 | }); 170 | 171 | update(); 172 | } 173 | 174 | function updateButtons() { 175 | // Remove existing fontsettings buttons 176 | if (!!BUTTON_ID) { 177 | gitbook.toolbar.removeButton(BUTTON_ID); 178 | } 179 | 180 | // Create buttons in toolbar 181 | BUTTON_ID = gitbook.toolbar.createButton({ 182 | icon: 'fa fa-font', 183 | label: 'Font Settings', 184 | className: 'font-settings', 185 | dropdown: [ 186 | [ 187 | { 188 | text: 'A', 189 | className: 'font-reduce', 190 | onClick: reduceFontSize 191 | }, 192 | { 193 | text: 'A', 194 | className: 'font-enlarge', 195 | onClick: enlargeFontSize 196 | } 197 | ], 198 | $.map(FAMILIES, function(family) { 199 | family.onClick = function(e) { 200 | return changeFontFamily(family.config, e); 201 | }; 202 | 203 | return family; 204 | }), 205 | $.map(THEMES, function(theme) { 206 | theme.onClick = function(e) { 207 | return changeColorTheme(theme.config, e); 208 | }; 209 | 210 | return theme; 211 | }) 212 | ] 213 | }); 214 | } 215 | 216 | // Init configuration at start 217 | gitbook.events.bind('start', function(e, config) { 218 | var opts = config.fontsettings; 219 | 220 | // Generate buttons at start 221 | updateButtons(); 222 | 223 | // Init current settings 224 | init(opts); 225 | }); 226 | 227 | // Expose API 228 | gitbook.fontsettings = { 229 | enlargeFontSize: enlargeFontSize, 230 | reduceFontSize: reduceFontSize, 231 | setTheme: changeColorTheme, 232 | setFamily: changeFontFamily, 233 | getThemes: getThemes, 234 | setThemes: setThemes, 235 | getFamilies: getFamilies, 236 | setFamilies: setFamilies 237 | }; 238 | }); 239 | 240 | 241 | -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-fontsettings/website.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Theme 1 3 | */ 4 | .color-theme-1 .dropdown-menu { 5 | background-color: #111111; 6 | border-color: #7e888b; 7 | } 8 | .color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { 9 | border-bottom: 9px solid #111111; 10 | } 11 | .color-theme-1 .dropdown-menu .buttons { 12 | border-color: #7e888b; 13 | } 14 | .color-theme-1 .dropdown-menu .button { 15 | color: #afa790; 16 | } 17 | .color-theme-1 .dropdown-menu .button:hover { 18 | color: #73553c; 19 | } 20 | /* 21 | * Theme 2 22 | */ 23 | .color-theme-2 .dropdown-menu { 24 | background-color: #2d3143; 25 | border-color: #272a3a; 26 | } 27 | .color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { 28 | border-bottom: 9px solid #2d3143; 29 | } 30 | .color-theme-2 .dropdown-menu .buttons { 31 | border-color: #272a3a; 32 | } 33 | .color-theme-2 .dropdown-menu .button { 34 | color: #62677f; 35 | } 36 | .color-theme-2 .dropdown-menu .button:hover { 37 | color: #f4f4f5; 38 | } 39 | .book .book-header .font-settings .font-enlarge { 40 | line-height: 30px; 41 | font-size: 1.4em; 42 | } 43 | .book .book-header .font-settings .font-reduce { 44 | line-height: 30px; 45 | font-size: 1em; 46 | } 47 | .book.color-theme-1 .book-body { 48 | color: #704214; 49 | background: #f3eacb; 50 | } 51 | .book.color-theme-1 .book-body .page-wrapper .page-inner section { 52 | background: #f3eacb; 53 | } 54 | .book.color-theme-2 .book-body { 55 | color: #bdcadb; 56 | background: #1c1f2b; 57 | } 58 | .book.color-theme-2 .book-body .page-wrapper .page-inner section { 59 | background: #1c1f2b; 60 | } 61 | .book.font-size-0 .book-body .page-inner section { 62 | font-size: 1.2rem; 63 | } 64 | .book.font-size-1 .book-body .page-inner section { 65 | font-size: 1.4rem; 66 | } 67 | .book.font-size-2 .book-body .page-inner section { 68 | font-size: 1.6rem; 69 | } 70 | .book.font-size-3 .book-body .page-inner section { 71 | font-size: 2.2rem; 72 | } 73 | .book.font-size-4 .book-body .page-inner section { 74 | font-size: 4rem; 75 | } 76 | .book.font-family-0 { 77 | font-family: Georgia, serif; 78 | } 79 | .book.font-family-1 { 80 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 81 | } 82 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { 83 | color: #704214; 84 | } 85 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { 86 | color: inherit; 87 | } 88 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 89 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, 90 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, 91 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, 92 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, 93 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 94 | color: inherit; 95 | } 96 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 97 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { 98 | border-color: inherit; 99 | } 100 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 101 | color: inherit; 102 | } 103 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { 104 | background-color: inherit; 105 | } 106 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { 107 | border-color: inherit; 108 | } 109 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, 110 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { 111 | background: #fdf6e3; 112 | color: #657b83; 113 | border-color: #f8df9c; 114 | } 115 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { 116 | background-color: inherit; 117 | } 118 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, 119 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { 120 | border-color: #f5d06c; 121 | } 122 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { 123 | color: inherit; 124 | background-color: #fdf6e3; 125 | border-color: #444444; 126 | } 127 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 128 | background-color: #fbeecb; 129 | } 130 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { 131 | color: #bdcadb; 132 | } 133 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { 134 | color: #3eb1d0; 135 | } 136 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 137 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, 138 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, 139 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, 140 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, 141 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 142 | color: #fffffa; 143 | } 144 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 145 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { 146 | border-color: #373b4e; 147 | } 148 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 149 | color: #373b4e; 150 | } 151 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { 152 | background-color: #373b4e; 153 | } 154 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { 155 | border-color: #373b4e; 156 | } 157 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, 158 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { 159 | color: #9dbed8; 160 | background: #2d3143; 161 | border-color: #2d3143; 162 | } 163 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { 164 | background-color: #282a39; 165 | } 166 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, 167 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { 168 | border-color: #3b3f54; 169 | } 170 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { 171 | color: #b6c2d2; 172 | background-color: #2d3143; 173 | border-color: #3b3f54; 174 | } 175 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 176 | background-color: #35394b; 177 | } 178 | .book.color-theme-1 .book-header { 179 | color: #afa790; 180 | background: transparent; 181 | } 182 | .book.color-theme-1 .book-header .btn { 183 | color: #afa790; 184 | } 185 | .book.color-theme-1 .book-header .btn:hover { 186 | color: #73553c; 187 | background: none; 188 | } 189 | .book.color-theme-1 .book-header h1 { 190 | color: #704214; 191 | } 192 | .book.color-theme-2 .book-header { 193 | color: #7e888b; 194 | background: transparent; 195 | } 196 | .book.color-theme-2 .book-header .btn { 197 | color: #3b3f54; 198 | } 199 | .book.color-theme-2 .book-header .btn:hover { 200 | color: #fffff5; 201 | background: none; 202 | } 203 | .book.color-theme-2 .book-header h1 { 204 | color: #bdcadb; 205 | } 206 | .book.color-theme-1 .book-body .navigation { 207 | color: #afa790; 208 | } 209 | .book.color-theme-1 .book-body .navigation:hover { 210 | color: #73553c; 211 | } 212 | .book.color-theme-2 .book-body .navigation { 213 | color: #383f52; 214 | } 215 | .book.color-theme-2 .book-body .navigation:hover { 216 | color: #fffff5; 217 | } 218 | /* 219 | * Theme 1 220 | */ 221 | .book.color-theme-1 .book-summary { 222 | color: #afa790; 223 | background: #111111; 224 | border-right: 1px solid rgba(0, 0, 0, 0.07); 225 | } 226 | .book.color-theme-1 .book-summary .book-search { 227 | background: transparent; 228 | } 229 | .book.color-theme-1 .book-summary .book-search input, 230 | .book.color-theme-1 .book-summary .book-search input:focus { 231 | border: 1px solid transparent; 232 | } 233 | .book.color-theme-1 .book-summary ul.summary li.divider { 234 | background: #7e888b; 235 | box-shadow: none; 236 | } 237 | .book.color-theme-1 .book-summary ul.summary li i.fa-check { 238 | color: #33cc33; 239 | } 240 | .book.color-theme-1 .book-summary ul.summary li.done > a { 241 | color: #877f6a; 242 | } 243 | .book.color-theme-1 .book-summary ul.summary li a, 244 | .book.color-theme-1 .book-summary ul.summary li span { 245 | color: #877f6a; 246 | background: transparent; 247 | font-weight: normal; 248 | } 249 | .book.color-theme-1 .book-summary ul.summary li.active > a, 250 | .book.color-theme-1 .book-summary ul.summary li a:hover { 251 | color: #704214; 252 | background: transparent; 253 | font-weight: normal; 254 | } 255 | /* 256 | * Theme 2 257 | */ 258 | .book.color-theme-2 .book-summary { 259 | color: #bcc1d2; 260 | background: #2d3143; 261 | border-right: none; 262 | } 263 | .book.color-theme-2 .book-summary .book-search { 264 | background: transparent; 265 | } 266 | .book.color-theme-2 .book-summary .book-search input, 267 | .book.color-theme-2 .book-summary .book-search input:focus { 268 | border: 1px solid transparent; 269 | } 270 | .book.color-theme-2 .book-summary ul.summary li.divider { 271 | background: #272a3a; 272 | box-shadow: none; 273 | } 274 | .book.color-theme-2 .book-summary ul.summary li i.fa-check { 275 | color: #33cc33; 276 | } 277 | .book.color-theme-2 .book-summary ul.summary li.done > a { 278 | color: #62687f; 279 | } 280 | .book.color-theme-2 .book-summary ul.summary li a, 281 | .book.color-theme-2 .book-summary ul.summary li span { 282 | color: #c1c6d7; 283 | background: transparent; 284 | font-weight: 600; 285 | } 286 | .book.color-theme-2 .book-summary ul.summary li.active > a, 287 | .book.color-theme-2 .book-summary ul.summary li a:hover { 288 | color: #f4f4f5; 289 | background: #252737; 290 | font-weight: 600; 291 | } 292 | -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-highlight/ebook.css: -------------------------------------------------------------------------------- 1 | pre, 2 | code { 3 | /* http://jmblog.github.io/color-themes-for-highlightjs */ 4 | /* Tomorrow Comment */ 5 | /* Tomorrow Red */ 6 | /* Tomorrow Orange */ 7 | /* Tomorrow Yellow */ 8 | /* Tomorrow Green */ 9 | /* Tomorrow Aqua */ 10 | /* Tomorrow Blue */ 11 | /* Tomorrow Purple */ 12 | } 13 | pre .hljs-comment, 14 | code .hljs-comment, 15 | pre .hljs-title, 16 | code .hljs-title { 17 | color: #8e908c; 18 | } 19 | pre .hljs-variable, 20 | code .hljs-variable, 21 | pre .hljs-attribute, 22 | code .hljs-attribute, 23 | pre .hljs-tag, 24 | code .hljs-tag, 25 | pre .hljs-regexp, 26 | code .hljs-regexp, 27 | pre .hljs-deletion, 28 | code .hljs-deletion, 29 | pre .ruby .hljs-constant, 30 | code .ruby .hljs-constant, 31 | pre .xml .hljs-tag .hljs-title, 32 | code .xml .hljs-tag .hljs-title, 33 | pre .xml .hljs-pi, 34 | code .xml .hljs-pi, 35 | pre .xml .hljs-doctype, 36 | code .xml .hljs-doctype, 37 | pre .html .hljs-doctype, 38 | code .html .hljs-doctype, 39 | pre .css .hljs-id, 40 | code .css .hljs-id, 41 | pre .css .hljs-class, 42 | code .css .hljs-class, 43 | pre .css .hljs-pseudo, 44 | code .css .hljs-pseudo { 45 | color: #c82829; 46 | } 47 | pre .hljs-number, 48 | code .hljs-number, 49 | pre .hljs-preprocessor, 50 | code .hljs-preprocessor, 51 | pre .hljs-pragma, 52 | code .hljs-pragma, 53 | pre .hljs-built_in, 54 | code .hljs-built_in, 55 | pre .hljs-literal, 56 | code .hljs-literal, 57 | pre .hljs-params, 58 | code .hljs-params, 59 | pre .hljs-constant, 60 | code .hljs-constant { 61 | color: #f5871f; 62 | } 63 | pre .ruby .hljs-class .hljs-title, 64 | code .ruby .hljs-class .hljs-title, 65 | pre .css .hljs-rules .hljs-attribute, 66 | code .css .hljs-rules .hljs-attribute { 67 | color: #eab700; 68 | } 69 | pre .hljs-string, 70 | code .hljs-string, 71 | pre .hljs-value, 72 | code .hljs-value, 73 | pre .hljs-inheritance, 74 | code .hljs-inheritance, 75 | pre .hljs-header, 76 | code .hljs-header, 77 | pre .hljs-addition, 78 | code .hljs-addition, 79 | pre .ruby .hljs-symbol, 80 | code .ruby .hljs-symbol, 81 | pre .xml .hljs-cdata, 82 | code .xml .hljs-cdata { 83 | color: #718c00; 84 | } 85 | pre .css .hljs-hexcolor, 86 | code .css .hljs-hexcolor { 87 | color: #3e999f; 88 | } 89 | pre .hljs-function, 90 | code .hljs-function, 91 | pre .python .hljs-decorator, 92 | code .python .hljs-decorator, 93 | pre .python .hljs-title, 94 | code .python .hljs-title, 95 | pre .ruby .hljs-function .hljs-title, 96 | code .ruby .hljs-function .hljs-title, 97 | pre .ruby .hljs-title .hljs-keyword, 98 | code .ruby .hljs-title .hljs-keyword, 99 | pre .perl .hljs-sub, 100 | code .perl .hljs-sub, 101 | pre .javascript .hljs-title, 102 | code .javascript .hljs-title, 103 | pre .coffeescript .hljs-title, 104 | code .coffeescript .hljs-title { 105 | color: #4271ae; 106 | } 107 | pre .hljs-keyword, 108 | code .hljs-keyword, 109 | pre .javascript .hljs-function, 110 | code .javascript .hljs-function { 111 | color: #8959a8; 112 | } 113 | pre .hljs, 114 | code .hljs { 115 | display: block; 116 | background: white; 117 | color: #4d4d4c; 118 | padding: 0.5em; 119 | } 120 | pre .coffeescript .javascript, 121 | code .coffeescript .javascript, 122 | pre .javascript .xml, 123 | code .javascript .xml, 124 | pre .tex .hljs-formula, 125 | code .tex .hljs-formula, 126 | pre .xml .javascript, 127 | code .xml .javascript, 128 | pre .xml .vbscript, 129 | code .xml .vbscript, 130 | pre .xml .css, 131 | code .xml .css, 132 | pre .xml .hljs-cdata, 133 | code .xml .hljs-cdata { 134 | opacity: 0.5; 135 | } 136 | -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-highlight/website.css: -------------------------------------------------------------------------------- 1 | .book .book-body .page-wrapper .page-inner section.normal pre, 2 | .book .book-body .page-wrapper .page-inner section.normal code { 3 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 4 | /* Tomorrow Comment */ 5 | /* Tomorrow Red */ 6 | /* Tomorrow Orange */ 7 | /* Tomorrow Yellow */ 8 | /* Tomorrow Green */ 9 | /* Tomorrow Aqua */ 10 | /* Tomorrow Blue */ 11 | /* Tomorrow Purple */ 12 | } 13 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, 14 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-comment, 15 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-title, 16 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-title { 17 | color: #8e908c; 18 | } 19 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, 20 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-variable, 21 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, 22 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, 23 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, 24 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-tag, 25 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, 26 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, 27 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, 28 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, 29 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, 30 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, 31 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, 32 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, 33 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, 34 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, 35 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, 36 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, 37 | .book .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, 38 | .book .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, 39 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, 40 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, 41 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, 42 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, 43 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, 44 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { 45 | color: #c82829; 46 | } 47 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-number, 48 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-number, 49 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, 50 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, 51 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, 52 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, 53 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, 54 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, 55 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, 56 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-literal, 57 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-params, 58 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-params, 59 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, 60 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-constant { 61 | color: #f5871f; 62 | } 63 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, 64 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, 65 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, 66 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { 67 | color: #eab700; 68 | } 69 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-string, 70 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-string, 71 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-value, 72 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-value, 73 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, 74 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, 75 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-header, 76 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-header, 77 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, 78 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-addition, 79 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, 80 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, 81 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 82 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 83 | color: #718c00; 84 | } 85 | .book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, 86 | .book .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { 87 | color: #3e999f; 88 | } 89 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-function, 90 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-function, 91 | .book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, 92 | .book .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, 93 | .book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, 94 | .book .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, 95 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, 96 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, 97 | .book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, 98 | .book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, 99 | .book .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, 100 | .book .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, 101 | .book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, 102 | .book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, 103 | .book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, 104 | .book .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { 105 | color: #4271ae; 106 | } 107 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, 108 | .book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, 109 | .book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, 110 | .book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { 111 | color: #8959a8; 112 | } 113 | .book .book-body .page-wrapper .page-inner section.normal pre .hljs, 114 | .book .book-body .page-wrapper .page-inner section.normal code .hljs { 115 | display: block; 116 | background: white; 117 | color: #4d4d4c; 118 | padding: 0.5em; 119 | } 120 | .book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, 121 | .book .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, 122 | .book .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, 123 | .book .book-body .page-wrapper .page-inner section.normal code .javascript .xml, 124 | .book .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 125 | .book .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, 126 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, 127 | .book .book-body .page-wrapper .page-inner section.normal code .xml .javascript, 128 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, 129 | .book .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, 130 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .css, 131 | .book .book-body .page-wrapper .page-inner section.normal code .xml .css, 132 | .book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 133 | .book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 134 | opacity: 0.5; 135 | } 136 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, 137 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { 138 | /* 139 | 140 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull 141 | 142 | */ 143 | /* Solarized Green */ 144 | /* Solarized Cyan */ 145 | /* Solarized Blue */ 146 | /* Solarized Yellow */ 147 | /* Solarized Orange */ 148 | /* Solarized Red */ 149 | /* Solarized Violet */ 150 | } 151 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs, 152 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs { 153 | display: block; 154 | padding: 0.5em; 155 | background: #fdf6e3; 156 | color: #657b83; 157 | } 158 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, 159 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, 160 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template_comment, 161 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template_comment, 162 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-header, 163 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-header, 164 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-doctype, 165 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-doctype, 166 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pi, 167 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pi, 168 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-string, 169 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-string, 170 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-javadoc, 171 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-javadoc { 172 | color: #93a1a1; 173 | } 174 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, 175 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, 176 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-winutils, 177 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-winutils, 178 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .method, 179 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .method, 180 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, 181 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, 182 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-tag, 183 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-tag, 184 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-request, 185 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-request, 186 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-status, 187 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-status, 188 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .nginx .hljs-title, 189 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .nginx .hljs-title { 190 | color: #859900; 191 | } 192 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, 193 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-number, 194 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-command, 195 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-command, 196 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, 197 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-string, 198 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag .hljs-value, 199 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-tag .hljs-value, 200 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-rules .hljs-value, 201 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-rules .hljs-value, 202 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-phpdoc, 203 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-phpdoc, 204 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 205 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, 206 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, 207 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, 208 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-hexcolor, 209 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-hexcolor, 210 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_url, 211 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_url { 212 | color: #2aa198; 213 | } 214 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, 215 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title, 216 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-localvars, 217 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-localvars, 218 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-chunk, 219 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-chunk, 220 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-decorator, 221 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-decorator, 222 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, 223 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, 224 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-identifier, 225 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-identifier, 226 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .vhdl .hljs-literal, 227 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .vhdl .hljs-literal, 228 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-id, 229 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-id, 230 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-function, 231 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-function { 232 | color: #268bd2; 233 | } 234 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, 235 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, 236 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, 237 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, 238 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-body, 239 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-body, 240 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .smalltalk .hljs-number, 241 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .smalltalk .hljs-number, 242 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, 243 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-constant, 244 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title, 245 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title, 246 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-parent, 247 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-parent, 248 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .haskell .hljs-type, 249 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .haskell .hljs-type, 250 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_reference, 251 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_reference { 252 | color: #b58900; 253 | } 254 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, 255 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, 256 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor .hljs-keyword, 257 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor .hljs-keyword, 258 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, 259 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, 260 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-shebang, 261 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-shebang, 262 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, 263 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, 264 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol .hljs-string, 265 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol .hljs-string, 266 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-change, 267 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-change, 268 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-special, 269 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-special, 270 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attr_selector, 271 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attr_selector, 272 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-subst, 273 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-subst, 274 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-cdata, 275 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-cdata, 276 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .clojure .hljs-title, 277 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .clojure .hljs-title, 278 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, 279 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo, 280 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, 281 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-header { 282 | color: #cb4b16; 283 | } 284 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, 285 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, 286 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-important, 287 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-important { 288 | color: #dc322f; 289 | } 290 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_label, 291 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_label { 292 | color: #6c71c4; 293 | } 294 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 295 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula { 296 | background: #eee8d5; 297 | } 298 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, 299 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { 300 | /* Tomorrow Night Bright Theme */ 301 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 302 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 303 | /* Tomorrow Comment */ 304 | /* Tomorrow Red */ 305 | /* Tomorrow Orange */ 306 | /* Tomorrow Yellow */ 307 | /* Tomorrow Green */ 308 | /* Tomorrow Aqua */ 309 | /* Tomorrow Blue */ 310 | /* Tomorrow Purple */ 311 | } 312 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, 313 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, 314 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, 315 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-title { 316 | color: #969896; 317 | } 318 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, 319 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, 320 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, 321 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, 322 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, 323 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-tag, 324 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, 325 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, 326 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, 327 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, 328 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, 329 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, 330 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, 331 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, 332 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, 333 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, 334 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, 335 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, 336 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, 337 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, 338 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, 339 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, 340 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, 341 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, 342 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, 343 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { 344 | color: #d54e53; 345 | } 346 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, 347 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-number, 348 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, 349 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, 350 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, 351 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, 352 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, 353 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, 354 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, 355 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-literal, 356 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-params, 357 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-params, 358 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, 359 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-constant { 360 | color: #e78c45; 361 | } 362 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, 363 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, 364 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, 365 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { 366 | color: #e7c547; 367 | } 368 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, 369 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-string, 370 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-value, 371 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-value, 372 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, 373 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, 374 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, 375 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-header, 376 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, 377 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, 378 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, 379 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, 380 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 381 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 382 | color: #b9ca4a; 383 | } 384 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, 385 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { 386 | color: #70c0b1; 387 | } 388 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-function, 389 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-function, 390 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, 391 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, 392 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, 393 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, 394 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, 395 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, 396 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, 397 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, 398 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, 399 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, 400 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, 401 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, 402 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, 403 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { 404 | color: #7aa6da; 405 | } 406 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, 407 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, 408 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, 409 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { 410 | color: #c397d8; 411 | } 412 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs, 413 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs { 414 | display: block; 415 | background: black; 416 | color: #eaeaea; 417 | padding: 0.5em; 418 | } 419 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, 420 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, 421 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, 422 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .xml, 423 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, 424 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, 425 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, 426 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .javascript, 427 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, 428 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, 429 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .css, 430 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .css, 431 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, 432 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { 433 | opacity: 0.5; 434 | } 435 | -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-livereload/plugin.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var newEl = document.createElement('script'), 3 | firstScriptTag = document.getElementsByTagName('script')[0]; 4 | 5 | if (firstScriptTag) { 6 | newEl.async = 1; 7 | newEl.src = '//' + window.location.hostname + ':35729/livereload.js'; 8 | firstScriptTag.parentNode.insertBefore(newEl, firstScriptTag); 9 | } 10 | 11 | })(); 12 | -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-lunr/lunr.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.5.12 3 | * Copyright (C) 2015 Oliver Nightingale 4 | * MIT Licensed 5 | * @license 6 | */ 7 | !function(){var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.5.12",t.utils={},t.utils.warn=function(t){return function(e){t.console&&console.warn&&console.warn(e)}}(this),t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var t=Array.prototype.slice.call(arguments),e=t.pop(),n=t;if("function"!=typeof e)throw new TypeError("last argument must be a function");n.forEach(function(t){this.hasHandler(t)||(this.events[t]=[]),this.events[t].push(e)},this)},t.EventEmitter.prototype.removeListener=function(t,e){if(this.hasHandler(t)){var n=this.events[t].indexOf(e);this.events[t].splice(n,1),this.events[t].length||delete this.events[t]}},t.EventEmitter.prototype.emit=function(t){if(this.hasHandler(t)){var e=Array.prototype.slice.call(arguments,1);this.events[t].forEach(function(t){t.apply(void 0,e)})}},t.EventEmitter.prototype.hasHandler=function(t){return t in this.events},t.tokenizer=function(t){return arguments.length&&null!=t&&void 0!=t?Array.isArray(t)?t.map(function(t){return t.toLowerCase()}):t.toString().trim().toLowerCase().split(/[\s\-]+/):[]},t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.registeredFunctions[e];if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},t.Pipeline.prototype.remove=function(t){var e=this._stack.indexOf(t);-1!=e&&this._stack.splice(e,1)},t.Pipeline.prototype.run=function(t){for(var e=[],n=t.length,i=this._stack.length,o=0;n>o;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;no;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;n element for each result 48 | res.results.forEach(function(res) { 49 | var $li = $('
        • ', { 50 | 'class': 'search-results-item' 51 | }); 52 | 53 | var $title = $('

          '); 54 | 55 | var $link = $('', { 56 | 'href': gitbook.state.basePath + '/' + res.url, 57 | 'text': res.title 58 | }); 59 | 60 | var content = res.body.trim(); 61 | if (content.length > MAX_DESCRIPTION_SIZE) { 62 | content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...'; 63 | } 64 | var $content = $('

          ').html(content); 65 | 66 | $link.appendTo($title); 67 | $title.appendTo($li); 68 | $content.appendTo($li); 69 | $li.appendTo($searchList); 70 | }); 71 | } 72 | 73 | function launchSearch(q) { 74 | // Add class for loading 75 | $body.addClass('with-search'); 76 | $body.addClass('search-loading'); 77 | 78 | // Launch search query 79 | throttle(gitbook.search.query(q, 0, MAX_RESULTS) 80 | .then(function(results) { 81 | displayResults(results); 82 | }) 83 | .always(function() { 84 | $body.removeClass('search-loading'); 85 | }), 1000); 86 | } 87 | 88 | function closeSearch() { 89 | $body.removeClass('with-search'); 90 | $bookSearchResults.removeClass('open'); 91 | } 92 | 93 | function launchSearchFromQueryString() { 94 | var q = getParameterByName('q'); 95 | if (q && q.length > 0) { 96 | // Update search input 97 | $searchInput.val(q); 98 | 99 | // Launch search 100 | launchSearch(q); 101 | } 102 | } 103 | 104 | function bindSearch() { 105 | // Bind DOM 106 | $searchInput = $('#book-search-input input'); 107 | $bookSearchResults = $('#book-search-results'); 108 | $searchList = $bookSearchResults.find('.search-results-list'); 109 | $searchTitle = $bookSearchResults.find('.search-results-title'); 110 | $searchResultsCount = $searchTitle.find('.search-results-count'); 111 | $searchQuery = $searchTitle.find('.search-query'); 112 | 113 | // Launch query based on input content 114 | function handleUpdate() { 115 | var q = $searchInput.val(); 116 | 117 | if (q.length == 0) { 118 | closeSearch(); 119 | } 120 | else { 121 | launchSearch(q); 122 | } 123 | } 124 | 125 | // Detect true content change in search input 126 | // Workaround for IE < 9 127 | var propertyChangeUnbound = false; 128 | $searchInput.on('propertychange', function(e) { 129 | if (e.originalEvent.propertyName == 'value') { 130 | handleUpdate(); 131 | } 132 | }); 133 | 134 | // HTML5 (IE9 & others) 135 | $searchInput.on('input', function(e) { 136 | // Unbind propertychange event for IE9+ 137 | if (!propertyChangeUnbound) { 138 | $(this).unbind('propertychange'); 139 | propertyChangeUnbound = true; 140 | } 141 | 142 | handleUpdate(); 143 | }); 144 | 145 | // Push to history on blur 146 | $searchInput.on('blur', function(e) { 147 | // Update history state 148 | if (usePushState) { 149 | var uri = updateQueryString('q', $(this).val()); 150 | history.pushState({ path: uri }, null, uri); 151 | } 152 | }); 153 | } 154 | 155 | gitbook.events.on('page.change', function() { 156 | bindSearch(); 157 | closeSearch(); 158 | 159 | // Launch search based on query parameter 160 | if (gitbook.search.isInitialized()) { 161 | launchSearchFromQueryString(); 162 | } 163 | }); 164 | 165 | gitbook.events.on('search.ready', function() { 166 | bindSearch(); 167 | 168 | // Launch search from query param at start 169 | launchSearchFromQueryString(); 170 | }); 171 | 172 | function getParameterByName(name) { 173 | var url = window.location.href; 174 | name = name.replace(/[\[\]]/g, '\\$&'); 175 | var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)', 'i'), 176 | results = regex.exec(url); 177 | if (!results) return null; 178 | if (!results[2]) return ''; 179 | return decodeURIComponent(results[2].replace(/\+/g, ' ')); 180 | } 181 | 182 | function updateQueryString(key, value) { 183 | value = encodeURIComponent(value); 184 | 185 | var url = window.location.href; 186 | var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'), 187 | hash; 188 | 189 | if (re.test(url)) { 190 | if (typeof value !== 'undefined' && value !== null) 191 | return url.replace(re, '$1' + key + '=' + value + '$2$3'); 192 | else { 193 | hash = url.split('#'); 194 | url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, ''); 195 | if (typeof hash[1] !== 'undefined' && hash[1] !== null) 196 | url += '#' + hash[1]; 197 | return url; 198 | } 199 | } 200 | else { 201 | if (typeof value !== 'undefined' && value !== null) { 202 | var separator = url.indexOf('?') !== -1 ? '&' : '?'; 203 | hash = url.split('#'); 204 | url = hash[0] + separator + key + '=' + value; 205 | if (typeof hash[1] !== 'undefined' && hash[1] !== null) 206 | url += '#' + hash[1]; 207 | return url; 208 | } 209 | else 210 | return url; 211 | } 212 | } 213 | }); 214 | -------------------------------------------------------------------------------- /_book/gitbook/gitbook-plugin-sharing/buttons.js: -------------------------------------------------------------------------------- 1 | require(['gitbook', 'jquery'], function(gitbook, $) { 2 | var SITES = { 3 | 'facebook': { 4 | 'label': 'Facebook', 5 | 'icon': 'fa fa-facebook', 6 | 'onClick': function(e) { 7 | e.preventDefault(); 8 | window.open('http://www.facebook.com/sharer/sharer.php?s=100&p[url]='+encodeURIComponent(location.href)); 9 | } 10 | }, 11 | 'twitter': { 12 | 'label': 'Twitter', 13 | 'icon': 'fa fa-twitter', 14 | 'onClick': function(e) { 15 | e.preventDefault(); 16 | window.open('http://twitter.com/home?status='+encodeURIComponent(document.title+' '+location.href)); 17 | } 18 | }, 19 | 'google': { 20 | 'label': 'Google+', 21 | 'icon': 'fa fa-google-plus', 22 | 'onClick': function(e) { 23 | e.preventDefault(); 24 | window.open('https://plus.google.com/share?url='+encodeURIComponent(location.href)); 25 | } 26 | }, 27 | 'weibo': { 28 | 'label': 'Weibo', 29 | 'icon': 'fa fa-weibo', 30 | 'onClick': function(e) { 31 | e.preventDefault(); 32 | window.open('http://service.weibo.com/share/share.php?content=utf-8&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)); 33 | } 34 | }, 35 | 'instapaper': { 36 | 'label': 'Instapaper', 37 | 'icon': 'fa fa-instapaper', 38 | 'onClick': function(e) { 39 | e.preventDefault(); 40 | window.open('http://www.instapaper.com/text?u='+encodeURIComponent(location.href)); 41 | } 42 | }, 43 | 'vk': { 44 | 'label': 'VK', 45 | 'icon': 'fa fa-vk', 46 | 'onClick': function(e) { 47 | e.preventDefault(); 48 | window.open('http://vkontakte.ru/share.php?url='+encodeURIComponent(location.href)); 49 | } 50 | } 51 | }; 52 | 53 | 54 | 55 | gitbook.events.bind('start', function(e, config) { 56 | var opts = config.sharing; 57 | 58 | // Create dropdown menu 59 | var menu = $.map(opts.all, function(id) { 60 | var site = SITES[id]; 61 | 62 | return { 63 | text: site.label, 64 | onClick: site.onClick 65 | }; 66 | }); 67 | 68 | // Create main button with dropdown 69 | if (menu.length > 0) { 70 | gitbook.toolbar.createButton({ 71 | icon: 'fa fa-share-alt', 72 | label: 'Share', 73 | position: 'right', 74 | dropdown: [menu] 75 | }); 76 | } 77 | 78 | // Direct actions to share 79 | $.each(SITES, function(sideId, site) { 80 | if (!opts[sideId]) return; 81 | 82 | gitbook.toolbar.createButton({ 83 | icon: site.icon, 84 | label: site.text, 85 | position: 'right', 86 | onClick: site.onClick 87 | }); 88 | }); 89 | }); 90 | }); 91 | -------------------------------------------------------------------------------- /_book/gitbook/images/apple-touch-icon-precomposed-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/images/apple-touch-icon-precomposed-152.png -------------------------------------------------------------------------------- /_book/gitbook/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/gitbook/images/favicon.ico -------------------------------------------------------------------------------- /_book/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 目录 · GitBook 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |

          68 |
          69 | 70 | 71 | 74 | 75 | 76 | 323 | 324 | 325 |
          326 | 327 |
          328 | 329 |
          330 | 331 | 332 | 333 | 342 | 343 | 344 | 345 | 346 |
          347 |
          348 | 349 |
          350 |
          351 | 352 |
          353 | 354 | 378 | 379 | 380 |
          381 | 382 |
          383 |
          384 |
          385 | 386 |

          results matching ""

          387 |
            388 | 389 |
            390 |
            391 | 392 |

            No results matching ""

            393 | 394 |
            395 |
            396 |
            397 | 398 |
            399 |
            400 | 401 |
            402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 |
            413 | 414 | 420 |
            421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | -------------------------------------------------------------------------------- /_book/res/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory=/Users/jukay/Desktop/hosts 3 | host_key_checking = True 4 | roles_path=./ 5 | deprecation_warnings=False 6 | library=./library 7 | -------------------------------------------------------------------------------- /_book/res/echo.retry: -------------------------------------------------------------------------------- 1 | aliyun 2 | -------------------------------------------------------------------------------- /_book/res/echo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 3 | hosts: aliyun 4 | remote_user: aliyun 5 | tasks: 6 | - name: 7 | shell: echo "Hello World" -------------------------------------------------------------------------------- /_book/res/golang/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | // Response 返回值 11 | type Response struct { 12 | Changed bool `json:"changed"` 13 | Fail bool `json:"fail"` 14 | Msg string `json:"msg"` 15 | RC int `json:"rc"` 16 | } 17 | 18 | func main() { 19 | var args = os.Args[:] 20 | var response Response 21 | if len(args) != 2 { 22 | response.Fail = true 23 | response.Msg = "失败" 24 | response.Changed = false 25 | } 26 | contents, err := readJSON(args[1]) 27 | if err != nil { 28 | response.Msg = err.Error() 29 | response.Fail = true 30 | response.Changed = false 31 | 32 | } else { 33 | var m = make(map[string]string) 34 | json.Unmarshal([]byte(contents), &m) 35 | response.Msg = " Hello " + m["name"] 36 | response.Fail = false 37 | response.Changed = false 38 | } 39 | 40 | buffer, _ := json.Marshal(response) 41 | fmt.Println(string(buffer)) 42 | } 43 | 44 | func readJSON(f string) (string, error) { 45 | fh, err := os.Open(f) 46 | if err != nil { 47 | return "", err 48 | } 49 | contents, err := ioutil.ReadAll(fh) 50 | return string(contents), err 51 | } 52 | -------------------------------------------------------------------------------- /_book/res/golang/write.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | ) 10 | 11 | // Response 返回值 12 | type Response struct { 13 | Changed bool `json:"changed"` 14 | Fail bool `json:"fail"` 15 | Msg string `json:"msg"` 16 | RC int `json:"rc"` 17 | } 18 | 19 | func readJSON(f string) (string, error) { 20 | fh, err := os.Open(f) 21 | if err != nil { 22 | return "", err 23 | } 24 | contents, err := ioutil.ReadAll(fh) 25 | return string(contents), err 26 | } 27 | 28 | func main() { 29 | var f = os.Args[1] 30 | res := Response{} 31 | ff, err := os.Open(f) 32 | if err != nil { 33 | res.Changed = false 34 | res.Fail = true 35 | res.Msg = "打开参数文件" + err.Error() 36 | returnJSON(res, 2) 37 | } 38 | contents, err := ioutil.ReadAll(ff) 39 | if err != nil { 40 | res.Changed = false 41 | res.Fail = true 42 | res.Msg = "读取参数文件失败" + err.Error() 43 | returnJSON(res, 2) 44 | } 45 | var m = make(map[string]interface{}) 46 | err = json.Unmarshal(contents, &m) 47 | if err != nil { 48 | res.Changed = false 49 | res.Fail = true 50 | res.Msg = "解析map出错" + err.Error() 51 | returnJSON(res, 2) 52 | } 53 | var path = m["path"] 54 | pathstring, _ := path.(string) 55 | fh, err := os.Create(pathstring) 56 | if err != nil { 57 | res.Changed = false 58 | res.Fail = true 59 | res.Msg = string(contents) 60 | returnJSON(res, 2) 61 | } 62 | defer fh.Close() 63 | var content = m["content"] 64 | contentstring, _ := content.(string) 65 | fh.Write([]byte(contentstring)) 66 | res.Changed = true 67 | res.Fail = false 68 | res.Msg = "success" 69 | returnJSON(res, 0) 70 | } 71 | 72 | func returnJSON(res Response, status int) { 73 | res.RC = status 74 | var out io.Writer 75 | if status == 0 { 76 | out = os.Stdout 77 | } else { 78 | out = os.Stderr 79 | } 80 | contents, _ := json.Marshal(res) 81 | fmt.Fprint(out, string(contents)) 82 | os.Exit(status) 83 | } 84 | -------------------------------------------------------------------------------- /_book/res/helloworld.retry: -------------------------------------------------------------------------------- 1 | aliyun 2 | -------------------------------------------------------------------------------- /_book/res/helloworld.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 3 | hosts: huanggai 4 | remote_user: deploy 5 | tasks: 6 | - name: Hello World版本的playbook 7 | hello: 8 | name: "{{ item }}" 9 | with_items: ["licong",caobo] -------------------------------------------------------------------------------- /_book/res/library/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/res/library/hello -------------------------------------------------------------------------------- /_book/res/library/write: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/_book/res/library/write -------------------------------------------------------------------------------- /_book/res/loop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: loop 3 | hosts: localhost 4 | remote_user: jukay 5 | tasks: 6 | - name: 7 | shell: echo Hello {{item}} 8 | with_items: "{{names}}" 9 | -------------------------------------------------------------------------------- /_book/res/preferences.fact: -------------------------------------------------------------------------------- 1 | hosts=aliyun -------------------------------------------------------------------------------- /_book/res/when.retry: -------------------------------------------------------------------------------- 1 | localhost 2 | -------------------------------------------------------------------------------- /_book/res/when.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: if条件 3 | hosts: localhost 4 | tasks: 5 | - name: 6 | shell: echo "Hello World" 7 | when: a == '10' 8 | -------------------------------------------------------------------------------- /_book/res/write.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 写入文件到服务器 3 | hosts: aliyun 4 | remote_user: root 5 | tasks: 6 | - name: 写文件 7 | write: 8 | path: /root/hello.txt 9 | content: Hello World 10 | sudo: yes -------------------------------------------------------------------------------- /doc/config.md: -------------------------------------------------------------------------------- 1 | # Ansible的配置 2 | ansible有一个ansible.cfg配置,可以指定ssh,hosts,library,roles等信息。这里要说明一下ansible是怎么查找这个配置文件的,因为这个很重要,很多人都不知道,查找顺序如下: 3 | 4 | * 从环境变量ANSIBLE_CONFIG 5 | * 当前目录的ansible.cfg 6 | * home目录的隐藏文件.ansible.cfg 7 | * /etc/ansible.cf文件 -------------------------------------------------------------------------------- /doc/hosts.md: -------------------------------------------------------------------------------- 1 | # Hosts文件介绍 2 |     Anasible管理者海量的机器,这些机器的ip和用户密码都配置在Ansible的hosts文件中,hosts文件默认是存在/etc/ansible/hosts这个地址,也是可以在运行过程中指定的,比如 3 | ```shell 4 | bash-3.2$ ansible huanggai -m command -a "echo hello world" -v -i /Users/jukay/Desktop/hosts 5 | No config file found; using defaults 6 | huanggai | SUCCESS | rc=0 >> 7 | hello world 8 | ``` 9 | 10 | ## 编写host文件 11 |     [Ansible](http://docs.ansible.com/)的hosts文件格式如下: 12 | 13 | 14 | ```txt 15 | 16 | [test] 17 | aliyun ansible_host=47.92.102.184 ansible_user=root ansible_ssh_private_key_file=~/.ssh/aliyun 18 | huanggai ansible_host=192.168.1.197 ansible_user=deploy ansible_ssh_port=9122 19 | 20 | [defualt] 21 | ansible_ssh_private_key_file=~/.ssh/aliyun 22 | baochai ansible_host=192.168.1.191 ansible_user=deploy ansible_ssh_port=9122 23 | daiyu ansible_host=192.168.1.192 ansible_user=deploy ansible_ssh_port=9122 24 | xiangyun ansible_host=192.168.1.193 ansible_user=deploy ansible_ssh_port=9122 25 | xifeng ansible_host=192.168.1.195 ansible_user=deploy ansible_ssh_port=9122 26 | xiren ansible_host=192.168.1.196 ansible_user=deploy ansible_ssh_port=9122 27 | huanggai ansible_host=192.168.1.197 ansible_user=deploy ansible_ssh_port=9122 28 | yuanchun ansible_host=192.168.1.224 ansible_user=deploy ansible_ssh_port=9122 29 | puppetmaster ansible_host=192.168.1.224 ansible_user=deploy ansible_ssh_port=9122 30 | hp ansible_host=192.168.1.225 ansible_user=deploy ansible_ssh_port=9122 31 | jira ansible_host=192.168.1.227 ansible_user=deploy ansible_ssh_port=9122 32 | caiyun ansible_host=192.168.1.234 ansible_user=deploy ansible_ssh_port=9122 33 | caohong ansible_host=192.168.2.49 ansible_user=deploy ansible_ssh_port=9122 34 | caozhi ansible_host=192.168.2.50 ansible_user=deploy ansible_ssh_port=9122 35 | caopi ansible_host=192.168.2.51 ansible_user=deploy ansible_ssh_port=9122 36 | caochong ansible_host=192.168.2.52 ansible_user=deploy ansible_ssh_port=9122 37 | ceshi ansible_host=47.92.102.184 ansible_user=deploy ansible_ssh_port=9122 38 | 39 | ``` 40 | 41 | [test]是什么意思? 42 | > [test]表示对机器进行了分组,这里aliyun和huanggai作为一组机器,组的名字叫test,其他机器座位一组,名字叫defualt,我们可以直接对着一组机器进操作,比如,我们直接调用ping模块来查看一组机器的网络情况 43 | ```shell 44 | bash-3.2$ ansible test -m ping -v -i /Users/jukay/Desktop/hosts 45 | No config file found; using defaults 46 | huanggai | SUCCESS => { 47 | "changed": false, 48 | "ping": "pong" 49 | } 50 | aliyun | SUCCESS => { 51 | "changed": false, 52 | "ping": "pong" 53 | } 54 | ``` 55 | 我们也可以一组机器加若干台机器一起执行命令 56 | ```shell 57 | bash-3.2$ ansible test,daiyu -m ping -v -i /Users/jukay/Desktop/hosts 58 | No config file found; using defaults 59 | daiyu | UNREACHABLE! => { 60 | "changed": false, 61 | "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n", 62 | "unreachable": true 63 | } 64 | huanggai | SUCCESS => { 65 | "changed": false, 66 | "ping": "pong" 67 | } 68 | aliyun | SUCCESS => { 69 | "changed": false, 70 | "ping": "pong" 71 | } 72 | ``` 73 | 74 | 75 | ansible_host是什么意思? 76 | > ansible_host表示目标机器的ip地址.如果这个地址如当前网络不通,那么ansible命令会返回UNREACHABLE! 77 | 78 | ansible_user是什么意思? 79 | > ansible_user表示登录到目标机器时候使用的用户账号。 80 | 81 | 82 | ansible_ssh_port是什么意思? 83 | > ansible_ssh_port是ansible通过ssh连接到目标机器时候使用的端口,默认是22号端口。 -------------------------------------------------------------------------------- /doc/introduction.md: -------------------------------------------------------------------------------- 1 | # Ansible简介 2 |     [Ansible](http://docs.ansible.com/)是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。 3 | ## Ansible的特点 4 |     [Ansible](http://docs.ansible.com/)是基于模块工作的,ansible本身是没有批量部署的能力,他只是提供了服务端通信功能,模块执行功能,以及一些核心的模块。还有一个比较特别的地方是:[Ansible](http://docs.ansible.com/)是不要安装客户端的,他只要求目标机器上安装了Python2.4以及以上版本即可。同时Ansible也是支持windows的. 5 | 6 | ## HelloWorld 7 | 8 | ```shell 9 | ~/C/M/ansible  ansible huanggai -m command -a "echo hello world" 1009ms  六 9/30 13:39:21 2017 10 | huanggai | SUCCESS | rc=0 >> 11 | hello world 12 | ``` 13 | 解释说明:huanggai 是指配置在/etc/ansible/hosts文件中的机器, -m 表示选择模块 command是[Ansible](http://docs.ansible.com/)的内置模块,-a表示的是command模块的参数 14 | ## 安装Ansible 15 | * mac:
            16 | brew install ansible 17 | * centos:
            18 | yum install ansible 19 | * ubuntu:
            20 | apt-get install ansible -------------------------------------------------------------------------------- /doc/modeul.md: -------------------------------------------------------------------------------- 1 | # 自定义模块 2 | 有时候官方自带的模块不能完成我们需要的功能,或者实现起来非常复杂的时候,这个时候我们也找不到开源的已有方案,我们可以考虑自己编写Ansible模块,他的使用方法和核心模块的使用方法是一样的。Ansible在设计的是并没有限制我们开发Ansible模块时候使用的语言。Ansible在2.2以后就支持二进制模块了,所以我们可以使用golang来编写Ansible模块。 3 | 4 | 首先,将模块文件读入内存,然后添加传递给模块的参数,最后将模块中所需要的类添加到内存,由zipfile压缩后,再由base64进行编码,写入到模版文件内。 5 | 6 | 通过默认的连接方式,一般是ssh。ansible通过ssh连接到远程主机,创建临时目录,并关闭连接。然后将打开另外一个ssh连接,将模版文件以sftp方式传送到刚刚创建的临时目录中,写完后关闭连接。然后打开一个ssh连接将任务对象赋予可执行权限,执行成功后关闭连接。 7 | 8 | 最后,ansible将打开第三个连接来执行模块,并删除临时目录及其所有内容。模块的结果是从标准输出stdout中获取json格式的字符串。ansible将解析和处理此字符串。如果有任务是异步控制执行的,ansible将在模块完成之前关闭第三个连接,并且返回主机后,在规定的时间内检查任务状态,直到模块完成或规定的时间超时。 9 | 10 | ## 读取参数 11 | 我们在使用golang开发模块的时候,面临一个问题:如何读取Ansible的参数?Ansible是将参数以json的形式写入到一个临时文件中,然后将这个临时文件的路径传给golang的命令行,我们可以用os.Args[1]来获取这个json文件。读取参数成功以后,我们就可以使用golang在目标机器上执行命令或者操作文件和网络等等。 12 | ```golang 13 | package main 14 | 15 | import ( 16 | "encoding/json" 17 | "fmt" 18 | "io/ioutil" 19 | "os" 20 | ) 21 | 22 | // Response 返回值 23 | type Response struct { 24 | Changed bool `json:"changed"` 25 | Fail bool `json:"fail"` 26 | Msg string `json:"msg"` 27 | RC int `json:"rc"` 28 | } 29 | 30 | func main() { 31 | var args = os.Args[:] 32 | var response Response 33 | if len(args) != 2 { 34 | response.Fail = true 35 | response.Msg = "失败" 36 | response.Changed = false 37 | } 38 | contents, err := readJSON(args[1]) 39 | if err != nil { 40 | response.Msg = err.Error() 41 | response.Fail = true 42 | response.Changed = false 43 | 44 | } else { 45 | var m = make(map[string]string) 46 | json.Unmarshal([]byte(contents), &m) 47 | response.Msg = " Hello " + m["name"] 48 | response.Fail = false 49 | response.Changed = false 50 | } 51 | 52 | buffer, _ := json.Marshal(response) 53 | fmt.Println(string(buffer)) 54 | } 55 | 56 | func readJSON(f string) (string, error) { 57 | fh, err := os.Open(f) 58 | if err != nil { 59 | return "", err 60 | } 61 | contents, err := ioutil.ReadAll(fh) 62 | return string(contents), err 63 | } 64 | 65 | ``` 66 | 67 | ## 返回值 68 | Ansible的返回值是一个json,他一般可能包括以下几个部分。 69 | 70 | 71 | |字段|类型|说明| 72 | |---|---|---| 73 | |backup_file|string|对于一些modules使用了backup变量,返回备份的文件路径| 74 | |changed|bool|表示任务是否对服务器进行了修改| 75 | |failed|bool|表示任务是否失败| 76 | |invocation|map|调用模块的方法| 77 | |msg|string|返回的消息| 78 | |rc|int|命令行程序的返回码| 79 | |results|map|如果该键存在,则表示该任务存在循环,并且它包含每个项目的模块“results”的列表| 80 | |skipped|bool|是否跳过执行| 81 | |stderr|string|标准错误输出| 82 | |stderr_lines|list|它将stderr字符串按行分割存储在列表中| 83 | |stdout|string|标准输出| 84 | |stdout_lines|list|它将stdout字符串按行分割存储在列表中| 85 | 86 | 87 | ## 如何使用自己写的模块 88 | 自动以的模块的使用方法和核心模块的使用方法基本是一致的,这里举个例子 89 | ```shell 90 | --- 91 | - name: 92 | hosts: aliyun 93 | remote_user: root 94 | tasks: 95 | - name: Hello World版本的playbook 96 | hello: 97 | name: "{{ item }}" 98 | with_items: ["licong",caobo] 99 | ``` 100 | 这里的hello就是上面的自定义模块,当然,我们也可以item参数改成从ansible参数传递一进去的形式。 101 | 使用golang开发Ansible模块的弊端就是无法跨平台,而python是可以跨平台执行的,而且golang在编译以后,二进制包的体积比较大,python开发的模块一般只有几kb大小。 -------------------------------------------------------------------------------- /doc/playbook.md: -------------------------------------------------------------------------------- 1 | # playbook 2 | 什么是playbook? 3 | > 4 | Playbooks 的格式是YAML(详见:YAML 语法),语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本,但它也并不是一个配置模型或过程的模型.playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用,这在前面章节学习过.‘plays’ 好似音符,playbook 好似由 ‘plays’ 构成的曲谱,通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 database server 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.“plays” 算是一个体育方面的类比,你可以通过多个 plays 告诉你的系统做不同的事情,不仅是定义一种特定的状态或模型.你可以在不同时间运行不同的 plays. 5 | 6 | 对初学者,这里有一个 playbook,其中仅包含一个 play: 7 | ```txt 8 | --- 9 | - hosts: webservers 10 | remote_user: root 11 | tasks: 12 | - name: ensure apache is at the latest version 13 | yum: pkg=httpd state=latest 14 | - name: write the apache config file 15 | template: src=/srv/httpd.j2 dest=/etc/httpd.conf 16 | notify: 17 | - restart apache 18 | - name: ensure apache is running 19 | service: name=httpd state=started 20 | handlers: 21 | - name: restart apache 22 | service: name=httpd state=restarted 23 | ``` 24 | ## Hello World 25 | 我们来编写一个Hello World版本的playbook 26 | ```txt 27 | --- 28 | - hosts: aliyun 29 | remote_user: root 30 | tasks: 31 | - name: Hello World版本的playbook 32 | shell: /bin/echo Hello World 33 | ``` 34 | 35 | ## 变量 36 |     上面的例子中,有些东西我们是写死了,不方复用。比如说hosts就可以写成变量形式 37 | ```txt 38 | --- 39 | - hosts: {{host}} 40 | remote_user: root 41 | tasks: 42 | - name: Hello World版本的playbook 43 | shell: /bin/echo Hello World 44 | ``` 45 | 这样我们可以在执行过程中,通过命令行参数吧host传进来,也可以吧Host变量的值写当前文件的preferences.fact文件中。 46 | ```shell 47 | ansible-playbook helloworld.yum -extra-vars="host=aliyun" 48 | ``` 49 | 这里我们-extra-vars参数传递了host参数到yml文件中,在Ansible的1.2版本以后是支持传json的 50 | ```txt 51 | –extra-vars ‘{“pacman”:”mrs”,”ghosts”:[“inky”,”pinky”,”clyde”,”sue”]}’ 52 | ``` 53 | 在Ansible的1.3版本以后,可以直接加载一个json文件 54 | ```txt 55 | –extra-vars “@some_file.json” 56 | ``` 57 | 58 | ## 条件 59 | Ansible在执行task的时候,是可以按照条件决定是否执行的 60 | ```shell 61 | --- 62 | - name: if条件 63 | hosts: localhost 64 | tasks: 65 | - name: 66 | shell: echo "Hello World" 67 | when: a == '10' 68 | 69 | ``` 70 | 执行 71 | ```shell 72 | ~/C/M/a/res  ansible-playbook if.yml --extra-vars "a=100" -v 1406ms  一 10/ 9 18:38:54 2017 73 | Using /Users/jukay/Code/Markdown/ansible/res/ansible.cfg as config file 74 | 75 | PLAY [if条件] ********************************************************************************************************************* 76 | 77 | TASK [Gathering Facts] ********************************************************************************************************** 78 | ok: [localhost] 79 | 80 | TASK [command] ****************************************************************************************************************** 81 | skipping: [localhost] => {"changed": false, "skip_reason": "Conditional result was False", "skipped": true} 82 | 83 | PLAY RECAP ********************************************************************************************************************** 84 | localhost : ok=1 changed=0 unreachable=0 failed=0 85 | ``` 86 | 这里提示条件不满足,跳过了 87 | 如果换一下参数 88 | ```shell 89 | Using /Users/jukay/Code/Markdown/ansible/res/ansible.cfg as config file 90 | 91 | PLAY [if条件] ********************************************************************************************************************* 92 | 93 | TASK [Gathering Facts] ********************************************************************************************************** 94 | ok: [localhost] 95 | 96 | TASK [command] ****************************************************************************************************************** 97 | changed: [localhost] => {"changed": true, "cmd": "echo \"Hello World\"", "delta": "0:00:00.007619", "end": "2017-10-09 18:41:01.170398", "rc": 0, "start": "2017-10-09 18:41:01.162779", "stderr": "", "stderr_lines": [], "stdout": "Hello World", "stdout_lines": ["Hello World"]} 98 | 99 | PLAY RECAP ********************************************************************************************************************** 100 | localhost : ok=2 changed=1 unreachable=0 failed=0 101 | ``` 102 | 这里标准输出就能成功输出Hello World。类型的条件判断还有 103 | 104 | * in 判断一个字符串是否存在另外一个字符串中 105 | * is define 判断一个变量是否定义 106 | * not 判断布尔类型是否为false 107 | * a|b 判断两个布尔类型是否至少一个为true 108 | * \> 或者 < 判断大小关系 109 | * or 和 | 一样 110 | * 等等。。。 111 | 112 | ## 迭代 113 | Ansible的参数是可以传列表的 114 | ```shell 115 | --- 116 | - name: loop 117 | hosts: localhost 118 | remote_user: jukay 119 | tasks: 120 | - name: 121 | shell: echo Hello {{item}} 122 | with_items: [licong,caobo] 123 | ``` 124 | 或者 125 | ```shell 126 | --- 127 | - name: loop 128 | hosts: localhost 129 | remote_user: jukay 130 | tasks: 131 | - name: 132 | shell: echo Hello {{item}} 133 | with_items: 134 | - licong 135 | - caobo 136 | ``` 137 | 迭代map和object数组都是可以的。 -------------------------------------------------------------------------------- /res/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory=./host 3 | host_key_checking = True 4 | roles_path=./ 5 | deprecation_warnings=False 6 | library=./library 7 | -------------------------------------------------------------------------------- /res/echo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 3 | hosts: aliyun 4 | remote_user: aliyun 5 | tasks: 6 | - name: 7 | shell: echo11 "Hello World" 8 | ignore_errors: yes 9 | - name: 10 | shell: echo "Hello World" -------------------------------------------------------------------------------- /res/golang/fuck.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Response 返回值的消息结构 8 | type Response struct { 9 | Changed bool `json:"changed"` 10 | Fail bool `json:"fail"` 11 | Msg string `json:"msg"` 12 | RC int `json:"rc"` 13 | } 14 | 15 | func main() { 16 | println("fuck") 17 | var res = Response{ 18 | Changed: false, 19 | Fail: false, 20 | Msg: "", 21 | RC: 0, 22 | } 23 | buf, _ := json.Marshal(res) 24 | println(string(buf)) 25 | } 26 | -------------------------------------------------------------------------------- /res/golang/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | // Response 返回值 11 | type Response struct { 12 | Changed bool `json:"changed"` 13 | Fail bool `json:"fail"` 14 | Msg string `json:"msg"` 15 | RC int `json:"rc"` 16 | } 17 | 18 | func main() { 19 | var args = os.Args[:] 20 | var response Response 21 | if len(args) != 2 { 22 | response.Fail = true 23 | response.Msg = "失败" 24 | response.Changed = false 25 | } 26 | contents, err := readJSON(args[1]) 27 | if err != nil { 28 | response.Msg = err.Error() 29 | response.Fail = true 30 | response.Changed = false 31 | 32 | } else { 33 | var m = make(map[string]string) 34 | json.Unmarshal([]byte(contents), &m) 35 | response.Msg = " Hello " + m["name"] 36 | response.Fail = false 37 | response.Changed = false 38 | } 39 | 40 | buffer, _ := json.Marshal(response) 41 | fmt.Println(string(buffer)) 42 | } 43 | 44 | func readJSON(f string) (string, error) { 45 | fh, err := os.Open(f) 46 | if err != nil { 47 | return "", err 48 | } 49 | contents, err := ioutil.ReadAll(fh) 50 | return string(contents), err 51 | } 52 | -------------------------------------------------------------------------------- /res/golang/write.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "os" 9 | ) 10 | 11 | // Response 返回值 12 | type Response struct { 13 | Changed bool `json:"changed"` 14 | Fail bool `json:"fail"` 15 | Msg string `json:"msg"` 16 | RC int `json:"rc"` 17 | } 18 | 19 | func readJSON(f string) (string, error) { 20 | fh, err := os.Open(f) 21 | if err != nil { 22 | return "", err 23 | } 24 | contents, err := ioutil.ReadAll(fh) 25 | return string(contents), err 26 | } 27 | 28 | func main() { 29 | var f = os.Args[1] 30 | res := Response{} 31 | ff, err := os.Open(f) 32 | if err != nil { 33 | res.Changed = false 34 | res.Fail = true 35 | res.Msg = "打开参数文件" + err.Error() 36 | returnJSON(res, 2) 37 | } 38 | contents, err := ioutil.ReadAll(ff) 39 | if err != nil { 40 | res.Changed = false 41 | res.Fail = true 42 | res.Msg = "读取参数文件失败" + err.Error() 43 | returnJSON(res, 2) 44 | } 45 | var m = make(map[string]interface{}) 46 | err = json.Unmarshal(contents, &m) 47 | if err != nil { 48 | res.Changed = false 49 | res.Fail = true 50 | res.Msg = "解析map出错" + err.Error() 51 | returnJSON(res, 2) 52 | } 53 | var path = m["path"] 54 | pathstring, _ := path.(string) 55 | fh, err := os.Create(pathstring) 56 | if err != nil { 57 | res.Changed = false 58 | res.Fail = true 59 | res.Msg = string(contents) 60 | returnJSON(res, 2) 61 | } 62 | defer fh.Close() 63 | var content = m["content"] 64 | contentstring, _ := content.(string) 65 | fh.Write([]byte(contentstring)) 66 | res.Changed = true 67 | res.Fail = false 68 | res.Msg = "success" 69 | returnJSON(res, 0) 70 | } 71 | 72 | func returnJSON(res Response, status int) { 73 | res.RC = status 74 | var out io.Writer 75 | if status == 0 { 76 | out = os.Stdout 77 | } else { 78 | out = os.Stderr 79 | } 80 | contents, _ := json.Marshal(res) 81 | fmt.Fprint(out, string(contents)) 82 | os.Exit(status) 83 | } 84 | -------------------------------------------------------------------------------- /res/helloworld.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 3 | hosts: huanggai 4 | remote_user: deploy 5 | tasks: 6 | - name: Hello World版本的playbook 7 | hello: 8 | name: "{{ item }}" 9 | with_items: ["licong",caobo] -------------------------------------------------------------------------------- /res/host: -------------------------------------------------------------------------------- 1 | [dev] 2 | 39.106.10.228 -------------------------------------------------------------------------------- /res/library/fuck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/res/library/fuck -------------------------------------------------------------------------------- /res/library/hello: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/res/library/hello -------------------------------------------------------------------------------- /res/library/write: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hellojukay/ansible/9fb6875a3eaeb733689c50fa70dc72415c5b386e/res/library/write -------------------------------------------------------------------------------- /res/loop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: loop 3 | hosts: localhost 4 | remote_user: jukay 5 | tasks: 6 | - name: 7 | shell: echo Hello {{item}} 8 | with_items: "{{names}}" 9 | -------------------------------------------------------------------------------- /res/preferences.fact: -------------------------------------------------------------------------------- 1 | hosts=aliyun -------------------------------------------------------------------------------- /res/when.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: if条件 3 | hosts: localhost 4 | tasks: 5 | - name: 6 | shell: echo "Hello World" 7 | when: a == '10' 8 | -------------------------------------------------------------------------------- /res/write.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 写入文件到服务器 3 | hosts: aliyun 4 | remote_user: root 5 | tasks: 6 | - name: 写文件 7 | write: 8 | path: /root/hello.txt 9 | content: Hello World 10 | sudo: yes --------------------------------------------------------------------------------