linecook 0.6.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/History +139 -0
  2. data/HowTo/Control Virtual Machines +106 -0
  3. data/HowTo/Generate Scripts +263 -0
  4. data/HowTo/Run Scripts +87 -0
  5. data/HowTo/Setup Virtual Machines +76 -0
  6. data/License.txt +1 -1
  7. data/README +78 -59
  8. data/bin/linecook +12 -5
  9. data/bin/linecook_run +45 -0
  10. data/bin/linecook_scp +50 -0
  11. data/lib/linecook.rb +1 -3
  12. data/lib/linecook/attributes.rb +49 -12
  13. data/lib/linecook/commands.rb +9 -4
  14. data/lib/linecook/commands/build.rb +69 -0
  15. data/lib/linecook/commands/command.rb +13 -3
  16. data/lib/linecook/commands/command_error.rb +6 -0
  17. data/lib/linecook/commands/env.rb +74 -8
  18. data/lib/linecook/commands/helper.rb +271 -24
  19. data/lib/linecook/commands/init.rb +10 -6
  20. data/lib/linecook/commands/package.rb +36 -18
  21. data/lib/linecook/commands/run.rb +66 -0
  22. data/lib/linecook/commands/snapshot.rb +114 -0
  23. data/lib/linecook/commands/ssh.rb +39 -0
  24. data/lib/linecook/commands/start.rb +34 -0
  25. data/lib/linecook/commands/state.rb +32 -0
  26. data/lib/linecook/commands/stop.rb +22 -0
  27. data/lib/linecook/commands/vbox_command.rb +130 -0
  28. data/lib/linecook/cookbook.rb +112 -55
  29. data/lib/linecook/package.rb +293 -109
  30. data/lib/linecook/proxy.rb +19 -0
  31. data/lib/linecook/recipe.rb +321 -62
  32. data/lib/linecook/template.rb +7 -101
  33. data/lib/linecook/test.rb +196 -141
  34. data/lib/linecook/test/command_parser.rb +75 -0
  35. data/lib/linecook/test/file_test.rb +153 -35
  36. data/lib/linecook/test/shell_test.rb +176 -0
  37. data/lib/linecook/utils.rb +25 -7
  38. data/lib/linecook/version.rb +4 -4
  39. data/templates/Rakefile +44 -47
  40. data/templates/_gitignore +1 -1
  41. data/templates/attributes/project_name.rb +4 -4
  42. data/templates/config/ssh +15 -0
  43. data/templates/files/help.txt +1 -0
  44. data/templates/helpers/project_name/assert_content_equal.erb +15 -0
  45. data/templates/helpers/project_name/create_dir.erb +9 -0
  46. data/templates/helpers/project_name/create_file.erb +8 -0
  47. data/templates/helpers/project_name/install_file.erb +8 -0
  48. data/templates/packages/abox.yml +4 -0
  49. data/templates/recipes/abox.rb +22 -0
  50. data/templates/recipes/abox_test.rb +14 -0
  51. data/templates/templates/todo.txt.erb +3 -0
  52. data/templates/test/project_name_test.rb +19 -0
  53. data/templates/test/test_helper.rb +14 -0
  54. metadata +43 -41
  55. data/cookbook +0 -0
  56. data/lib/linecook/commands/helpers.rb +0 -28
  57. data/lib/linecook/commands/vbox.rb +0 -85
  58. data/lib/linecook/helper.rb +0 -117
  59. data/lib/linecook/shell.rb +0 -11
  60. data/lib/linecook/shell/posix.rb +0 -145
  61. data/lib/linecook/shell/test.rb +0 -254
  62. data/lib/linecook/shell/unix.rb +0 -117
  63. data/lib/linecook/shell/utils.rb +0 -138
  64. data/templates/README +0 -90
  65. data/templates/files/file.txt +0 -1
  66. data/templates/helpers/project_name/echo.erb +0 -5
  67. data/templates/recipes/project_name.rb +0 -20
  68. data/templates/scripts/project_name.yml +0 -7
  69. data/templates/templates/template.txt.erb +0 -3
  70. data/templates/vbox/setup/virtual_box +0 -86
  71. data/templates/vbox/ssh/id_rsa +0 -27
  72. data/templates/vbox/ssh/id_rsa.pub +0 -1
@@ -0,0 +1,87 @@
1
+ = Run Scripts
2
+
3
+ Linecook runs scripts using the 'run' command. Internally run copies scripts
4
+ to a server using scp and then executes the script using ssh. More
5
+ specifically run copies a *package* to the server and executes a script within
6
+ the package using ssh. A package is simply a directory containing scripts and
7
+ any files the scripts use.
8
+
9
+ To manually recreate what run does, make a directory with an script, copy it,
10
+ and execute as below (assuming you set up the 'abox' server {as described
11
+ earlier}[link:files/Tutorial/1%20-%20VM%20Setup.html]). Note that the script
12
+ is made executable locally such that scp will make the script executable on
13
+ the server.
14
+
15
+ mkdir demo
16
+ cat > demo/script.sh <<"DOC"
17
+ echo "# $(whoami)@$(hostname): hello world!"
18
+ DOC
19
+ chmod +x demo/script.sh
20
+
21
+ scp -r -P 2220 demo linecook@localhost:/tmp/demo
22
+ ssh -p 2220 linecook@localhost -- "/tmp/demo/script.sh"
23
+ # linecook@abox-ubuntu: hello world!
24
+
25
+ To simplify this a little, move the redundant information used by scp and ssh
26
+ can into a standard ssh config file. Linecook looks for an ssh config file in
27
+ 'config/ssh' by default:
28
+
29
+ mkdir config
30
+ cat > config/ssh <<DOC
31
+ Host abox
32
+ User linecook
33
+ HostName localhost
34
+ Port 2220
35
+ DOC
36
+
37
+ Now run will copy the package under the 'packages' directory with the same
38
+ name as the Host config, and execute the specified script:
39
+
40
+ mkdir packages
41
+ mv demo packages/abox
42
+ linecook run --script script.sh abox
43
+ # linecook@abox-ubuntu: hello world!
44
+
45
+ To run multiple packages at once, simply add more hosts to the ssh config
46
+ file. Run copies each package to the appropriate host and then runs the same
47
+ script on each (in alphabetic order by host). So say you also set up a 'bbox'
48
+ same as 'abox':
49
+
50
+ cat >> config/ssh <<DOC
51
+ Host abox
52
+ Port 2220
53
+
54
+ Host bbox
55
+ Port 2221
56
+
57
+ Host *
58
+ User linecook
59
+ HostName localhost
60
+ DOC
61
+ cp packages/abox packages/bbox
62
+
63
+ Then:
64
+
65
+ linecook run --script script.sh abox bbox
66
+ # linecook@abox-ubuntu: hello world!
67
+ # linecook@bbox-ubuntu: hello world!
68
+
69
+ Note that by default run will execute the 'run' script on all hosts configured
70
+ in 'config/ssh'. Leveraging these defaults simplifies the last command:
71
+
72
+ mv packages/abox/script.sh packages/abox/run
73
+ mv packages/bbox/script.sh packages/bbox/run
74
+ linecook run
75
+ # linecook@abox-ubuntu: hello world!
76
+ # linecook@bbox-ubuntu: hello world!
77
+
78
+ If you've never used scp/ssh with a config file then this may seem unfamiliar
79
+ but hopefully quite graceful. For scp/ssh masters, these are equivalent for
80
+ each host:
81
+
82
+ linecook run --remote-dir=/tmp/linecook SCRIPT ARGS...
83
+
84
+ scp -q -r -p -F config/ssh packages/host "host:/tmp/linecook"
85
+ ssh -q -t -t -F config/ssh host -- "/tmp/linecook/SCRIPT ARGS..."
86
+
87
+ Now that you can run scripts, onward to generating scripts!
@@ -0,0 +1,76 @@
1
+ = Setup Virtual Machines
2
+
3
+ {VirtualBox}[http://www.virtualbox.org] runs virtual machines on your local
4
+ box. Local VMs help minimize development cycles because they are quick to
5
+ access and reset. In addition, VirtualBox allows snapshots which can save and
6
+ restore a particular server state - this functionality enables iterative
7
+ development.
8
+
9
+ To set up a Ubuntu VM using VirtualBox:
10
+
11
+ 1. Download and Install VirtualBox (http://www.virtualbox.org)
12
+ 2. Download a Ubuntu ISO (http://www.ubuntu.com/server/get-ubuntu/download)
13
+ 3. Build the Box
14
+
15
+ When done, see the documentation for {controlling
16
+ VMs}[link:files/HowTo/Control%20Virtual%20Machines.html]
17
+
18
+ == Building a Ubuntu Box
19
+
20
+ Use the VirtualBox wizard to get started. The name and other settings (ex
21
+ user, ssh port) may be changed but be sure to propagate changes throughout the
22
+ setup process.
23
+
24
+ - name: abox
25
+ - Linux/Ubuntu
26
+ - 512 MB memory
27
+ - 8 GB dynamically resizing drive
28
+
29
+ Add the Ubuntu iso to the cd/dvd device under Settings > Storage. Now start
30
+ the server and install Ubuntu (use default settings unless specified):
31
+
32
+ - hostname: abox-ubuntu
33
+ - user/password: linecook
34
+ - select 'OpenSSH server' in packages to install
35
+
36
+ When the server has rebooted and is at the login screen, remove the install
37
+ iso, take a snapshot, and setup port forwarding. Port forwarding allows you to
38
+ access the ssh port (22) on the VM via a port on your local box (2220).
39
+
40
+ (Devices > CD/DVD Devices > Remove disk from virtual drive)
41
+ VBoxManage snapshot abox take RAW
42
+ VBoxManage controlvm abox poweroff
43
+ # wait to fully power off
44
+ VBoxManage modifyvm abox --natpf1 'abox-ssh,tcp,,2220,,22'
45
+ VBoxManage -q snapshot abox restore RAW
46
+ VBoxManage startvm abox
47
+
48
+ Transfer your ssh key to the VM (notice port 2220). Help to generate ssh keys
49
+ can be found on {GitHub}[http://help.github.com/key-setup-redirect]:
50
+
51
+ scp -P 2220 -o UserKnownHostsFile=/dev/null ~/.ssh/id_rsa.pub linecook@localhost:id_rsa.pub
52
+
53
+ Login as linecook and setup SSH access:
54
+
55
+ vm: mkdir .ssh
56
+ vm: mv id_rsa.pub .ssh/authorized_keys
57
+ vm: chmod 0700 .ssh
58
+ vm: chmod 0600 .ssh/authorized_keys
59
+
60
+ Remove the login banner (as a convenience) and exit:
61
+
62
+ vm: sudo rm /etc/motd
63
+ vm: exit
64
+
65
+ Now take a base snapshot:
66
+
67
+ VBoxManage snapshot abox take BASE
68
+ VBoxManage controlvm abox poweroff
69
+
70
+ To cleanup port forwarding (run later, if ever):
71
+
72
+ VBoxManage modifyvm abox --natpf1 delete 'abox-ssh'
73
+
74
+ The same procedure can be repeated to build other VMs. Nothing is special
75
+ about this setup. The os, name, port, and other settings may be changed to
76
+ your liking - all that Linecook requires is ssh access.
data/License.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Pinnacol Assurance
1
+ Copyright (c) 2010-2011 Pinnacol Assurance
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -4,95 +4,114 @@ A shell script generator.
4
4
 
5
5
  == Description
6
6
 
7
- Linecook lets you generate shell scripts using an extensible set of tiny ERB
8
- helpers. The helpers output a shell script that you can use to (for example)
9
- provision a server.
7
+ Linecook generates shell scripts using an extensible set of ERB helpers. The
8
+ shell scripts and associated resources (files, subscripts, etc) make up
9
+ packages that can be used, for example, to provision servers.
10
10
 
11
- The workflow is like this:
11
+ Linecook provides a command line tool to manage development servers, generate
12
+ scripts, and run scripts on servers. Helpers and recipes can be shared as
13
+ gems; the canonical shell helpers are available through
14
+ {Linebook}[http://rubygems.org/gems/linebook/].
12
15
 
13
- * define helpers
14
- * write a recipe using the helpers
15
- * generate a script from the recipe
16
+ See the documentation for help to:
16
17
 
17
- Linecook provides very basic helpers for POSIX shells and a command-line tool
18
- for generating scripts and running them on a test vm.
18
+ * {Setup}[link:files/HowTo/Setup%20Virtual%20Machines.html] and {Control}[link:files/HowTo/Control%20Virtual%20Machines.html] Virtual Machines
19
+ * {Generate Scripts}[link:files/HowTo/Generate%20Scripts.html]
20
+ * {Run Scripts}[link:files/HowTo/Run%20Scripts.html]
19
21
 
20
22
  == Usage
21
23
 
22
- Generate a cookbook.
24
+ Generate a project.
23
25
 
24
- % linecook init example
25
- % cd example
26
+ % linecook init chalkboard
27
+ % cd chalkboard
26
28
 
27
- Make some helpers.
29
+ Define default attributes.
28
30
 
29
- [helpers/example/_head.rb]
30
- COLOR_CODES = Hash[*%W{
31
- black 0;30 red 0;31
32
- white 1;37 green 0;32
33
- light_gray 0;37 blue 0;34
34
- }]
35
-
36
- [helpers/example/color.erb]
37
- Adds color to a string.
31
+ [attributes/chalkboard.rb]
32
+ attrs['chalkboard']['n'] = 3
33
+ attrs['chalkboard']['color'] = 'white'
34
+ attrs['chalkboard']['message'] = 'I will not manually configure my server'
35
+
36
+ Define a helper.
37
+
38
+ [helpers/chalkboard/echo_in_color.erb]
39
+ Echo a string in color.
38
40
  (color, str)
41
+ color_codes = Hash[*%W{
42
+ black 0;30 red 0;31
43
+ white 1;37 green 0;32
44
+ light_gray 0;37 blue 0;34
45
+ }]
39
46
  --
40
- \033[<%= COLOR_CODES[color.to_s] %>m<%= str %>\033[0m
47
+ echo -e '\033[<%= color_codes[color.to_s] %>m<%= str %>\033[0m'
48
+
49
+ Use both in a recipe.
50
+
51
+ [recipes/chalkboard.rb]
52
+ attributes "chalkboard"
53
+ helpers "chalkboard"
41
54
 
42
- [helpers/example/echo.erb]
43
- Echo a string in color
44
- (str, options={})
45
- color = options[:color]
46
- --
47
- echo -e '<%= color ? _color(color, str) : str %>'
55
+ attrs['chalkboard']['n'].times do
56
+ echo_in_color attrs['chalkboard']['color'], attrs['chalkboard']['message']
57
+ end
48
58
 
49
- Define default attributes.
59
+ Define a package to use the recipe; set non-default attributes as needed.
50
60
 
51
- [recipes/example.rb]
52
- attrs['example']['n'] = 3
53
- attrs['example']['color'] = 'blue'
61
+ [packages/chalkboard.yml]
62
+ chalkboard:
63
+ n: 5
64
+ color: blue
54
65
 
55
- Use them in a recipe.
66
+ Generate the package from the attributes, helpers, and recipe.
56
67
 
57
- [recipes/example.rb]
58
- helpers "example"
59
- attributes "example"
60
-
61
- attrs['example']['n'].times do
62
- echo "I will not manually configure my server", :color => attrs['example']['color']
63
- end
68
+ % linecook build
64
69
 
65
- Define a script using the recipe.
70
+ Check the packages directory to see the resulting script.
66
71
 
67
- [scripts/example.yml]
68
- linecook:
69
- recipe_name: example
70
- script_name: example.sh
71
- example:
72
- n: 100
72
+ % cat packages/chalkboard/run
73
+ echo -e '\033[0;34mI will not manually configure my server\033[0m'
74
+ echo -e '\033[0;34mI will not manually configure my server\033[0m'
75
+ echo -e '\033[0;34mI will not manually configure my server\033[0m'
76
+ echo -e '\033[0;34mI will not manually configure my server\033[0m'
77
+ echo -e '\033[0;34mI will not manually configure my server\033[0m'
73
78
 
74
- Generate a script from the helpers, attributes, and recipe.
79
+ Now run the package.
75
80
 
76
- % rake scripts
81
+ % linecook run
77
82
 
78
- Start the VM and run the scripts (see the docs for setting up a VM).
83
+ The package can be run on any server accessible via ssh. See the generated
84
+ 'config/ssh' file as well as the documentation for {Running Scripts on
85
+ Servers}[link:files/HowTo/Run%20Scripts.html].
79
86
 
80
- % rake vbox:start
81
- % rake vbox:ssh
82
- vm: bash /vbox/scripts/example.sh
83
- vm: exit
87
+ == Composition
84
88
 
85
- Stop the VM.
89
+ Linecook consists of the following.
90
+
91
+ = Components =
92
+ attributes
93
+ helpers
94
+ |-----> recipes -> packages -a-> (scripts) -b-> (servers) <-c- server setup
95
+ files
96
+ templates
97
+
98
+ = Commands =
99
+ ex: 'linecook build' on the command line
100
+
101
+ a) env, helper, package, build # build scripts
102
+ b) run # run scripts
103
+ c) start, stop, ssh, snapshot, reset # server setup/control
86
104
 
87
- % rake vbox:stop
105
+ Everything to the left of 'scripts' has to do with generating scripts;
106
+ everything to the right with running scripts on servers.
88
107
 
89
108
  == Installation
90
109
 
91
- Linecook is available as a gem on {Gemcutter}[http://gemcutter.org/gems/linecook]
110
+ Linecook is available as a {gem}[http://rubygems.org/gems/linecook].
92
111
 
93
112
  % gem install linecook
94
113
 
95
114
  == Info
96
115
 
97
- Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com]
116
+ Developer:: {Simon Chiang}[http://github.com/thinkerbot]
98
117
  License:: {MIT-Style}[link:files/License_txt.html]
data/bin/linecook CHANGED
@@ -1,5 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ if File.exists?('Gemfile')
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ Bundler.setup
7
+ end
8
+
3
9
  require 'linecook/version'
4
10
  require 'linecook/commands'
5
11
  registry = Linecook::Commands::Command.registry
@@ -24,7 +30,7 @@ if cmd_class.nil?
24
30
 
25
31
  exit
26
32
  when '-v', '--version'
27
- puts "version #{Linecook::VERSION} -- #{Linecook::WEBSITE}"
33
+ puts "linecook version #{Linecook::VERSION} -- #{Linecook::WEBSITE}"
28
34
  exit
29
35
  else
30
36
  puts "unknown command: #{cmd.inspect}"
@@ -37,10 +43,10 @@ parser.add cmd_class.configurations
37
43
  parser.on '-h', '--help', 'print this help' do
38
44
  puts "usage: linecook [options] #{cmd} #{cmd_class.args}"
39
45
 
40
- desc = cmd_class.desc.wrap
46
+ desc = cmd_class.desc.wrap(76, 2, "\n ")
41
47
  unless desc.empty?
42
48
  puts
43
- puts cmd_class.desc.wrap
49
+ puts " #{desc}"
44
50
  puts
45
51
  end
46
52
 
@@ -53,6 +59,7 @@ parser.parse! ARGV
53
59
  begin
54
60
  cmd_class.new(parser.config).call ARGV
55
61
  rescue Linecook::Commands::CommandError
56
- puts $!.message
57
- exit 1
62
+ puts $!.message unless $!.message.strip.empty?
63
+ puts $!.backtrace if $DEBUG
64
+ exit $!.exitstatus
58
65
  end
data/bin/linecook_run ADDED
@@ -0,0 +1,45 @@
1
+ #! /bin/sh
2
+ ############################################################################
3
+
4
+ ssh_config_file=${SSH_CONFIG_FILE:-config/ssh}
5
+ remote_dir=${REMOTE_DIR:-$(pwd)/linecook}
6
+ remote_script=${REMOTE_SCRIPT:-run}
7
+
8
+ usage="usage: %s [-F SSH_CONFIG_FILE] [-D REMOTE_DIR] [-S REMOTE_SCRIPT] [-h] PACKAGE_DIRS...\n"
9
+ option=" %s %s\n"
10
+ while getopts "F:D:S:h" opt
11
+ do
12
+ case $opt in
13
+ F ) ssh_config_file=$OPTARG ;;
14
+ D ) remote_dir=$OPTARG ;;
15
+ S ) remote_script=$OPTARG ;;
16
+ h ) printf "$usage" $0
17
+ printf "$option" "-F" "the ssh config file"
18
+ printf "$option" "-D" "the remote package dir"
19
+ printf "$option" "-S" "the remote script"
20
+ printf "$option" "-h" "prints this help"
21
+ exit 0 ;;
22
+ \? ) printf "$usage" $0
23
+ exit 2 ;;
24
+ esac
25
+ done
26
+ shift $(($OPTIND - 1))
27
+
28
+ ################################### run ####################################
29
+
30
+ for package_dir in "$@"
31
+ do
32
+ host=$(basename -- "$package_dir")
33
+
34
+ ssh -q -t -t -F "$ssh_config_file" "$host" -- "$remote_dir/$remote_script" 2>/dev/null </dev/null
35
+
36
+ status=$?
37
+ if [ $status -ne 0 ]
38
+ then
39
+ echo "[$status] $remote_dir/$remote_script" >&2
40
+ exit 1
41
+ fi
42
+
43
+ done
44
+
45
+ ################################## (run) ###################################
data/bin/linecook_scp ADDED
@@ -0,0 +1,50 @@
1
+ #! /bin/sh
2
+ ############################################################################
3
+
4
+ ssh_config_file=${SSH_CONFIG_FILE:-config/ssh}
5
+ remote_dir=${REMOTE_DIR:-\$(pwd)/linecook}
6
+
7
+ usage="usage: %s [-D REMOTE_DIR] [-F SSH_CONFIG_FILE] [-h] PACKAGE_DIRS...\n"
8
+ option=" %s %s\n"
9
+ while getopts "F:D:h" opt
10
+ do
11
+ case $opt in
12
+ F ) ssh_config_file=$OPTARG ;;
13
+ D ) remote_dir=$OPTARG ;;
14
+ h ) printf "$usage" $0
15
+ printf "$option" "-F" "the ssh config file"
16
+ printf "$option" "-D" "the remote package dir"
17
+ printf "$option" "-h" "prints this help"
18
+ exit 0 ;;
19
+ \? ) printf "$usage" $0
20
+ exit 2 ;;
21
+ esac
22
+ done
23
+ shift $(($OPTIND - 1))
24
+
25
+ ################################### scp ####################################
26
+
27
+ for package_dir in "$@"
28
+ do
29
+ host=$(basename -- "$package_dir")
30
+
31
+ ssh -q -T -F "$ssh_config_file" "$host" -- <<SCRIPT
32
+ rm -rf "$remote_dir"
33
+ if [ "\$(dirname "$remote_dir")" != "" ]
34
+ then
35
+ mkdir -p "\$(dirname "$remote_dir")"
36
+ fi
37
+ SCRIPT
38
+
39
+ scp -q -r -p -F "$ssh_config_file" "$package_dir" "$host:$remote_dir"
40
+
41
+ status=$?
42
+ if [ $status -ne 0 ]
43
+ then
44
+ echo "[$status] $remote_dir/$script_name " >&2
45
+ exit 1
46
+ fi
47
+ done
48
+
49
+ ################################## (scp) ###################################
50
+