houcho 0.0.6 → 0.0.8
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Gemfile.lock +32 -0
- data/bin/houcho +3 -262
- data/houcho.gemspec +2 -1
- data/lib/houcho/attribute.rb +99 -0
- data/lib/houcho/ci.rb +18 -13
- data/lib/houcho/cli/attribute.rb +70 -0
- data/lib/houcho/cli/host.rb +46 -0
- data/lib/houcho/cli/outerrole.rb +53 -0
- data/lib/houcho/cli/role.rb +69 -0
- data/lib/houcho/cli/spec.rb +103 -0
- data/lib/houcho/cli.rb +52 -0
- data/lib/houcho/config.rb +28 -0
- data/lib/houcho/database.rb +99 -0
- data/lib/houcho/element.rb +79 -50
- data/lib/houcho/host.rb +30 -9
- data/lib/houcho/outerrole/cloudforecast.rb +94 -0
- data/{templates/role/cf_roles.yaml → lib/houcho/outerrole/yabitz.rb} +0 -0
- data/lib/houcho/outerrole.rb +52 -0
- data/lib/houcho/repository.rb +59 -0
- data/lib/houcho/role.rb +78 -91
- data/lib/houcho/spec/runner.rb +156 -85
- data/lib/houcho/spec.rb +72 -3
- data/lib/houcho/version.rb +1 -1
- data/lib/houcho.rb +10 -52
- data/spec/houcho_spec.rb +334 -91
- metadata +31 -22
- data/lib/houcho/cloudforecast/host.rb +0 -25
- data/lib/houcho/cloudforecast/role.rb +0 -25
- data/lib/houcho/cloudforecast.rb +0 -59
- data/lib/houcho/yamlhandle.rb +0 -31
- data/spec/spec_helper.rb +0 -15
- data/templates/conf/houcho.conf +0 -10
- data/templates/conf/kk.rb +0 -14
- data/templates/conf/rspec.conf +0 -1
- data/templates/master +0 -94
- data/templates/role/cloudforecast/.gitkeep +0 -0
- data/templates/role/cloudforecast.yaml +0 -0
- data/templates/role/hosts.yaml +0 -0
- data/templates/role/hosts_ignored.yaml +0 -0
- data/templates/role/roles.yaml +0 -0
- data/templates/role/specs.yaml +0 -0
- data/templates/spec/sample_spec.rb +0 -13
- data/templates/spec/spec_helper.rb +0 -29
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0d83d0e90621526a1a46014365dc3a97deb67f9a
         | 
| 4 | 
            +
              data.tar.gz: cc2c9dc65df3b0b5145d9c3f02769f2b2c555fb6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f6fa79952eacf76bc3ba07ce6b9b8007a51d4ca7b5fe9d3b679f7d909fa8844fe3c01acc95e213ba60fe06bdc74212d3223ff36d5551920c04337a7494f5b1ef
         | 
| 7 | 
            +
              data.tar.gz: 07aece03104359e42827386d89869fc6229cfeb283c45bf66cbea6de42db114151728bdca051593e41b5ba43d5ccf18f985ab899b08849fbdf8f21309ba6dd16
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            GEM
         | 
| 2 | 
            +
              remote: https://rubygems.org/
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                diff-lcs (1.2.4)
         | 
| 5 | 
            +
                highline (1.6.19)
         | 
| 6 | 
            +
                net-ssh (2.6.8)
         | 
| 7 | 
            +
                parallel (0.7.1)
         | 
| 8 | 
            +
                parallel_tests (0.15.0)
         | 
| 9 | 
            +
                  parallel
         | 
| 10 | 
            +
                rainbow (1.1.4)
         | 
| 11 | 
            +
                rspec (2.13.0)
         | 
| 12 | 
            +
                  rspec-core (~> 2.13.0)
         | 
| 13 | 
            +
                  rspec-expectations (~> 2.13.0)
         | 
| 14 | 
            +
                  rspec-mocks (~> 2.13.0)
         | 
| 15 | 
            +
                rspec-core (2.13.1)
         | 
| 16 | 
            +
                rspec-expectations (2.13.0)
         | 
| 17 | 
            +
                  diff-lcs (>= 1.1.3, < 2.0)
         | 
| 18 | 
            +
                rspec-mocks (2.13.1)
         | 
| 19 | 
            +
                serverspec (0.7.0)
         | 
| 20 | 
            +
                  highline
         | 
| 21 | 
            +
                  net-ssh
         | 
| 22 | 
            +
                  rspec (~> 2.13.0)
         | 
| 23 | 
            +
                systemu (2.5.2)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            PLATFORMS
         | 
| 26 | 
            +
              ruby
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            DEPENDENCIES
         | 
| 29 | 
            +
              parallel_tests
         | 
| 30 | 
            +
              rainbow
         | 
| 31 | 
            +
              serverspec
         | 
| 32 | 
            +
              systemu
         | 
    
        data/bin/houcho
    CHANGED
    
    | @@ -1,263 +1,4 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
            require 'rubygems'
         | 
| 6 | 
            -
            require 'thor'
         | 
| 7 | 
            -
            require 'houcho'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            include Houcho
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            module Helper
         | 
| 12 | 
            -
              module_function
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              def empty_args(klass, chell, mesod)
         | 
| 15 | 
            -
                klass.class.task_help(chell, mesod)
         | 
| 16 | 
            -
                exit
         | 
| 17 | 
            -
              end
         | 
| 18 | 
            -
            end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            class Thor::MyHelper < Thor
         | 
| 21 | 
            -
              class_option :help, :type => :boolean, :aliases => '-h', :desc => 'Help message.'
         | 
| 22 | 
            -
             | 
| 23 | 
            -
              no_tasks do
         | 
| 24 | 
            -
                def invoke_task(task, *args)
         | 
| 25 | 
            -
                  if options[:help] && task.name != 'help'
         | 
| 26 | 
            -
                    self.class.task_help(shell, task.name)
         | 
| 27 | 
            -
                  else
         | 
| 28 | 
            -
                    super
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
              end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
              def self.banner(task, namespace = false, subcommand = true)
         | 
| 34 | 
            -
                super
         | 
| 35 | 
            -
              end
         | 
| 36 | 
            -
            end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
            class SpecConduct < Thor::MyHelper
         | 
| 40 | 
            -
              namespace :spec
         | 
| 41 | 
            -
             | 
| 42 | 
            -
              desc 'details [spec1 spec2 spec3...]', 'show details about spec'
         | 
| 43 | 
            -
              def details(*args)
         | 
| 44 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 45 | 
            -
                puts_details(Spec.details(args))
         | 
| 46 | 
            -
              end
         | 
| 47 | 
            -
             | 
| 48 | 
            -
              desc 'show', 'show all of specs'
         | 
| 49 | 
            -
              def show
         | 
| 50 | 
            -
                puts Spec.elements.sort.join("\n")
         | 
| 51 | 
            -
              end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
              desc 'attach [spec1 spec2 spec3...] --roles [role1 role2...]', 'attach spec to role'
         | 
| 54 | 
            -
              option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 55 | 
            -
              def attach(*args)
         | 
| 56 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 57 | 
            -
                Spec.attach(args, options[:roles]) rescue puts $!.message; exit!
         | 
| 58 | 
            -
              end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
              desc 'detach [spec1 spec2 spec3...] --roles [role1 role2...]', 'detach spec from spec'
         | 
| 61 | 
            -
              option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 62 | 
            -
              def detach(*args)
         | 
| 63 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 64 | 
            -
                Spec.detach(args, options[:roles]) rescue puts $!.message; exit!
         | 
| 65 | 
            -
              end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
              desc 'check [options]', 'run the spec sampled appropriately to the associated host'
         | 
| 68 | 
            -
              option :sample_host_count, :type => :numeric, :default => 5, :desc => 'number of sample hosts'
         | 
| 69 | 
            -
              def check(*args)
         | 
| 70 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                begin
         | 
| 73 | 
            -
                  messages = Spec::Runner.check(args, options[:sample_host_count])
         | 
| 74 | 
            -
                rescue
         | 
| 75 | 
            -
                  puts $!.message
         | 
| 76 | 
            -
                  exit!
         | 
| 77 | 
            -
                end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                messages.each do |msg|
         | 
| 80 | 
            -
                  puts msg
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
              end
         | 
| 83 | 
            -
             | 
| 84 | 
            -
              desc 'exec (spec1 spec2..) [options]', 'run serverspec manually'
         | 
| 85 | 
            -
              option :hosts,   :type => :array,   :desc => '--hosts host1 host2 host3...', :required => true
         | 
| 86 | 
            -
              option :ukigumo, :type => :boolean, :desc => 'post results to UkigumoServer'
         | 
| 87 | 
            -
              option :ikachan, :type => :boolean, :desc => 'post fail results to Ikachan'
         | 
| 88 | 
            -
              option :dry_run, :type => :boolean, :desc => 'show commands that may exexute'
         | 
| 89 | 
            -
              def exec(*args)
         | 
| 90 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                begin
         | 
| 93 | 
            -
                  messages = Spec::Runner.exec(
         | 
| 94 | 
            -
                    [], [], options[:hosts], args,
         | 
| 95 | 
            -
                    {
         | 
| 96 | 
            -
                      ukigumo: options[:ukigumo],
         | 
| 97 | 
            -
                      ikachan: options[:ikachan],
         | 
| 98 | 
            -
                    },
         | 
| 99 | 
            -
                    options[:dry_run],
         | 
| 100 | 
            -
                  )
         | 
| 101 | 
            -
                rescue
         | 
| 102 | 
            -
                  puts $!.message
         | 
| 103 | 
            -
                  exit!
         | 
| 104 | 
            -
                end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                messages.each do |msg|
         | 
| 107 | 
            -
                  puts msg
         | 
| 108 | 
            -
                end
         | 
| 109 | 
            -
              end
         | 
| 110 | 
            -
            end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
            class HostConduct < Thor::MyHelper
         | 
| 114 | 
            -
              namespace :host
         | 
| 115 | 
            -
             | 
| 116 | 
            -
              desc 'details [host1 host2 host3...]', 'show details about host'
         | 
| 117 | 
            -
              def details(*args)
         | 
| 118 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 119 | 
            -
                puts_details(Host.details(args))
         | 
| 120 | 
            -
              end
         | 
| 121 | 
            -
             | 
| 122 | 
            -
              desc 'show', 'show all of hosts'
         | 
| 123 | 
            -
              def show
         | 
| 124 | 
            -
                puts (Host.elements + CloudForecast::Host.all).join("\n")
         | 
| 125 | 
            -
              end
         | 
| 126 | 
            -
             | 
| 127 | 
            -
              desc 'attach [host1 host2 host3...] --roles [role1 role2...]', 'attach host to role'
         | 
| 128 | 
            -
              option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 129 | 
            -
              def attach(*args)
         | 
| 130 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 131 | 
            -
                Host.attach(args, options[:roles]) rescue puts $!.message; exit!
         | 
| 132 | 
            -
              end
         | 
| 133 | 
            -
             | 
| 134 | 
            -
              desc 'detach [host1 host2 host3...] --roles [role1 role2...]', 'detach host from role'
         | 
| 135 | 
            -
              option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 136 | 
            -
              def detach(*args)
         | 
| 137 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 138 | 
            -
                Host.detach(args, options[:roles]) rescue puts $!.message; exit!
         | 
| 139 | 
            -
              end
         | 
| 140 | 
            -
            end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
            class RoleConduct < Thor::MyHelper
         | 
| 144 | 
            -
              namespace :role
         | 
| 145 | 
            -
             | 
| 146 | 
            -
              desc 'create [role1 role2 role3...]', 'cretate role'
         | 
| 147 | 
            -
              def create(*args)
         | 
| 148 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 149 | 
            -
                Role.create(args) rescue puts $!.message; exit!
         | 
| 150 | 
            -
              end
         | 
| 151 | 
            -
             | 
| 152 | 
            -
              desc 'delete [role1 role2 role3...]', 'delete a role'
         | 
| 153 | 
            -
              def delete(*args)
         | 
| 154 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 155 | 
            -
                Role.delete(args) rescue puts $!.message; exit!
         | 
| 156 | 
            -
              end
         | 
| 157 | 
            -
             | 
| 158 | 
            -
              desc 'rename [exist role] [name]', 'rename a role'
         | 
| 159 | 
            -
              def rename(role, rename)
         | 
| 160 | 
            -
                Role.rename(role, rename) rescue puts $!.message; exit!
         | 
| 161 | 
            -
              end
         | 
| 162 | 
            -
             | 
| 163 | 
            -
              desc 'details [role1 role2...]', 'show details about role'
         | 
| 164 | 
            -
              def details(*args)
         | 
| 165 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 166 | 
            -
                puts_details(Role.details(args))
         | 
| 167 | 
            -
              end
         | 
| 168 | 
            -
             | 
| 169 | 
            -
              desc 'show', 'show all of roles'
         | 
| 170 | 
            -
              def show
         | 
| 171 | 
            -
                puts Role.all.join("\n")
         | 
| 172 | 
            -
              end
         | 
| 173 | 
            -
             | 
| 174 | 
            -
              desc 'exec (role1 role2..) [options]', 'run role'
         | 
| 175 | 
            -
              option :exclude_hosts, :type => :array, :desc => '--exclude-hosts host1 host2 host3...'
         | 
| 176 | 
            -
              option :ukigumo, :type => :boolean, :desc => 'post results to UkigumoServer'
         | 
| 177 | 
            -
              option :ikachan, :type => :boolean, :desc => 'post fail results to Ikachan'
         | 
| 178 | 
            -
              option :dry_run, :type => :boolean, :desc => 'show commands that may exexute'
         | 
| 179 | 
            -
              def exec(*args)
         | 
| 180 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 181 | 
            -
             | 
| 182 | 
            -
                begin
         | 
| 183 | 
            -
                  messages = Spec::Runner.exec(
         | 
| 184 | 
            -
                    args, (options[:exclude_hosts]||[]), [], [],
         | 
| 185 | 
            -
                    {
         | 
| 186 | 
            -
                      ukigumo: options[:ukigumo],
         | 
| 187 | 
            -
                      ikachan: options[:ikachan],
         | 
| 188 | 
            -
                    },
         | 
| 189 | 
            -
                    options[:dry_run],
         | 
| 190 | 
            -
                  )
         | 
| 191 | 
            -
                rescue
         | 
| 192 | 
            -
                  puts $!.message
         | 
| 193 | 
            -
                  exit!
         | 
| 194 | 
            -
                end
         | 
| 195 | 
            -
             | 
| 196 | 
            -
                messages.each do |msg|
         | 
| 197 | 
            -
                  puts msg
         | 
| 198 | 
            -
                end
         | 
| 199 | 
            -
              end
         | 
| 200 | 
            -
            end
         | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
            class CFConduct < Thor::MyHelper
         | 
| 204 | 
            -
              namespace :cf
         | 
| 205 | 
            -
             | 
| 206 | 
            -
              desc "details [cf1 cf2 cf3...]", "show details about cloudforecast's role"
         | 
| 207 | 
            -
              def details(*args)
         | 
| 208 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 209 | 
            -
                puts_details(CloudForecast::Role.details(args))
         | 
| 210 | 
            -
              end
         | 
| 211 | 
            -
             | 
| 212 | 
            -
              desc 'show', "show all of cloudforecast's roles"
         | 
| 213 | 
            -
              def show
         | 
| 214 | 
            -
                puts CloudForecast::Role.all.sort.join("\n")
         | 
| 215 | 
            -
              end
         | 
| 216 | 
            -
             | 
| 217 | 
            -
              desc 'attach [cf1 cf2 cf3...] --roles [role1 role2...]', "attach cloudforecast's role to role"
         | 
| 218 | 
            -
              option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 219 | 
            -
              def attach(*args)
         | 
| 220 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 221 | 
            -
                CloudForecast::Role.attach(args, options[:roles]) rescue puts $!.message; exit!
         | 
| 222 | 
            -
              end
         | 
| 223 | 
            -
             | 
| 224 | 
            -
              desc 'detach [cf1 cf2 cf3...] --roles [role1 role2...]', "detach cloudforecast's role from role"
         | 
| 225 | 
            -
              option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 226 | 
            -
              def detach(*args)
         | 
| 227 | 
            -
                Helper.empty_args(self, shell, __method__) if args.empty?
         | 
| 228 | 
            -
                CloudForecast::Role.detach(args, options[:roles]) rescue puts $!.message; exit!
         | 
| 229 | 
            -
              end
         | 
| 230 | 
            -
             | 
| 231 | 
            -
              desc 'load', '(re)loading yamls of cloudforecast'
         | 
| 232 | 
            -
              def load
         | 
| 233 | 
            -
                CloudForecast.load_yaml
         | 
| 234 | 
            -
              end
         | 
| 235 | 
            -
            end
         | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
            class Main < Thor
         | 
| 239 | 
            -
              register(CFConduct,   'cf',   'cf [attach|detach|show|details|load]', 'operate relevant to CloudForecast')
         | 
| 240 | 
            -
              register(RoleConduct, 'role', 'role [create|delete|rename|show|details|exec]', 'operate roles')
         | 
| 241 | 
            -
              register(HostConduct, 'host', 'host [attach|detach|show|details]', 'operate hosts')
         | 
| 242 | 
            -
              register(SpecConduct, 'spec', 'spec [attach|detach|show|details|exec|check]', 'operate specs')
         | 
| 243 | 
            -
             | 
| 244 | 
            -
              class_option :help, :type => :boolean, :aliases => '-h', :desc => 'Help message.'
         | 
| 245 | 
            -
              no_tasks do
         | 
| 246 | 
            -
                def invoke_task(task, *args)
         | 
| 247 | 
            -
                  if options[:help] && ! %w{role host spec cf help}.include?(task.name)
         | 
| 248 | 
            -
                    Houcho.task_help(shell, task.name)
         | 
| 249 | 
            -
                  else
         | 
| 250 | 
            -
                    super
         | 
| 251 | 
            -
                  end
         | 
| 252 | 
            -
                end
         | 
| 253 | 
            -
              end
         | 
| 254 | 
            -
             | 
| 255 | 
            -
              desc 'init', 'set houcho repository on current directory'
         | 
| 256 | 
            -
              def init
         | 
| 257 | 
            -
                init_repo
         | 
| 258 | 
            -
              end
         | 
| 259 | 
            -
             | 
| 260 | 
            -
            end
         | 
| 261 | 
            -
             | 
| 262 | 
            -
            Main.start
         | 
| 263 | 
            -
            exit! if $houcho_fail
         | 
| 2 | 
            +
            $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
         | 
| 3 | 
            +
            require 'houcho/cli'
         | 
| 4 | 
            +
            Houcho::CLI::Main.start
         | 
    
        data/houcho.gemspec
    CHANGED
    
    | @@ -20,9 +20,10 @@ Gem::Specification.new do |spec| | |
| 20 20 |  | 
| 21 21 | 
             
              spec.add_runtime_dependency 'thor'
         | 
| 22 22 | 
             
              spec.add_runtime_dependency 'rainbow'
         | 
| 23 | 
            -
              spec.add_runtime_dependency ' | 
| 23 | 
            +
              spec.add_runtime_dependency 'parallel'
         | 
| 24 24 | 
             
              spec.add_runtime_dependency 'systemu'
         | 
| 25 25 | 
             
              spec.add_runtime_dependency 'serverspec'
         | 
| 26 | 
            +
              spec.add_runtime_dependency 'sqlite3-ruby'
         | 
| 26 27 | 
             
              spec.add_development_dependency "bundler", "~> 1.3"
         | 
| 27 28 | 
             
              spec.add_development_dependency "rake"
         | 
| 28 29 | 
             
              spec.add_development_dependency "tmpdir"
         | 
| @@ -0,0 +1,99 @@ | |
| 1 | 
            +
            require "houcho/database"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Houcho
         | 
| 4 | 
            +
              class AttributeExceptiotn < Exception; end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              module Attribute
         | 
| 7 | 
            +
                def attr_id(attr_name)
         | 
| 8 | 
            +
                  id = @db.execute("SELECT id FROM attribute WHERE name = ?", attr_name)
         | 
| 9 | 
            +
                  raise AttributeExceptiotn, "attribute does not exist - #{attr_name}" unless id
         | 
| 10 | 
            +
                  id.flatten.first
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
             | 
| 14 | 
            +
                def set_attr!(target, attr)
         | 
| 15 | 
            +
                  set_attr(target, attr, true)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def set_attr(target, attr, force = false)
         | 
| 19 | 
            +
                  target_id = id(target)
         | 
| 20 | 
            +
                  raise_target_does_not_exist(target) if target_id.nil?
         | 
| 21 | 
            +
                  @db.transaction do
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  attr.each do |name, attr_value|
         | 
| 24 | 
            +
                    attr_name = name.to_s
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    begin
         | 
| 27 | 
            +
                      @db.execute("INSERT INTO attribute(name) VALUES(?)", attr_name)
         | 
| 28 | 
            +
                    rescue SQLite3::ConstraintException, "column name is not unique"
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    begin
         | 
| 32 | 
            +
                      @db.execute(
         | 
| 33 | 
            +
                        "INSERT INTO attribute_value(attr_id, element_type, element_id, value) VALUES(?,?,?,?)",
         | 
| 34 | 
            +
                        attr_id(attr_name),
         | 
| 35 | 
            +
                        @type_id,
         | 
| 36 | 
            +
                        target_id,
         | 
| 37 | 
            +
                        attr_value
         | 
| 38 | 
            +
                      )
         | 
| 39 | 
            +
                    rescue SQLite3::ConstraintException, "columns attr_id, element_type, element_id are not unique"
         | 
| 40 | 
            +
                      if force
         | 
| 41 | 
            +
                        @db.execute("
         | 
| 42 | 
            +
                          UPDATE attribute_value SET value = ?
         | 
| 43 | 
            +
                          WHERE attr_id = ? AND element_type = ? AND element_id = ?
         | 
| 44 | 
            +
                        ", attr_value, attr_id(attr_name), @type_id, target_id)
         | 
| 45 | 
            +
                      else
         | 
| 46 | 
            +
                        raise AttributeExceptiotn, "attribute has already defined value in #{@type} - #{attr_name}"
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  end #end of transaction
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
             | 
| 55 | 
            +
                def get_attr_json(target, name = nil)
         | 
| 56 | 
            +
                  get_attr(target, name, true)
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
             | 
| 60 | 
            +
                def get_attr(target, attr_name = nil, json = false)
         | 
| 61 | 
            +
                  target_id = id(target)
         | 
| 62 | 
            +
                  return json ? "{}" : {} if target_id.nil?
         | 
| 63 | 
            +
                  attr = {}
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  id_value = @db.execute("
         | 
| 66 | 
            +
                    SELECT attr_id, value FROM attribute_value
         | 
| 67 | 
            +
                    WHERE element_type = ? AND element_id = ?
         | 
| 68 | 
            +
                  ", @type_id, target_id)
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  id_value.each do |iv|
         | 
| 71 | 
            +
                    name = @db.execute("SELECT name FROM attribute WHERE id = ?", iv[0]).first.first
         | 
| 72 | 
            +
                    attr[name.to_sym] = iv[1]
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  attr = attr.select { |k,v| k == attr_name.to_sym } if attr_name
         | 
| 76 | 
            +
                  attr = JSON.generate(attr) if json
         | 
| 77 | 
            +
                  attr
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
             | 
| 81 | 
            +
                def del_attr(target, attr_name = nil)
         | 
| 82 | 
            +
                  before_delete = get_attr(target, attr_name)
         | 
| 83 | 
            +
                  sql = "DELETE FROM attribute_value WHERE element_type = ? AND element_id = ?"
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  @db.transaction do
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  if attr_name
         | 
| 88 | 
            +
                    sql += " AND attr_id = ?"
         | 
| 89 | 
            +
                    @db.execute(sql, @type_id, id(target), attr_id(attr_name))
         | 
| 90 | 
            +
                  else
         | 
| 91 | 
            +
                    @db.execute(sql, @type_id, id(target))
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  end #end of transaction
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  before_delete
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
            end
         | 
    
        data/lib/houcho/ci.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 1 2 | 
             
            require 'net/http'
         | 
| 2 3 | 
             
            require 'uri'
         | 
| 3 4 |  | 
| @@ -9,17 +10,18 @@ end | |
| 9 10 | 
             
            module Houcho::CI
         | 
| 10 11 | 
             
              class UkigumoClient
         | 
| 11 12 | 
             
                def initialize(server, port = 80, url = "http://#{server}:#{port}")
         | 
| 12 | 
            -
                  @ukigumo_server | 
| 13 | 
            +
                  @ukigumo_server = server
         | 
| 13 14 | 
             
                  @ukigumo_listen_port = port
         | 
| 14 | 
            -
                  @ukigumo_base_url | 
| 15 | 
            +
                  @ukigumo_base_url = url
         | 
| 15 16 | 
             
                end
         | 
| 16 17 |  | 
| 17 18 | 
             
                def search(elements, limit = 1)
         | 
| 18 | 
            -
                  query_string = 
         | 
| 19 | 
            -
                     | 
| 20 | 
            -
                     | 
| 21 | 
            -
                     | 
| 22 | 
            -
                     | 
| 19 | 
            +
                  query_string = URI.encode_www_form({
         | 
| 20 | 
            +
                    :project  => elements[:project].to_s,
         | 
| 21 | 
            +
                    :branch   => elements[:branch].to_s,
         | 
| 22 | 
            +
                    :revision => elements[:revision].to_s,
         | 
| 23 | 
            +
                    :limit    => limit.to_s,
         | 
| 24 | 
            +
                  })
         | 
| 23 25 |  | 
| 24 26 | 
             
                  Net::HTTP.start(@ukigumo_server, @ukigumo_listen_port) do |http|
         | 
| 25 27 | 
             
                    responce = http.get("/api/v1/report/search?#{query_string}")
         | 
| @@ -28,7 +30,7 @@ module Houcho::CI | |
| 28 30 | 
             
                end
         | 
| 29 31 |  | 
| 30 32 | 
             
                def post(elements)
         | 
| 31 | 
            -
                  Net::HTTP.post_form(
         | 
| 33 | 
            +
                  response = Net::HTTP.post_form(
         | 
| 32 34 | 
             
                    URI.parse("#{@ukigumo_base_url}/api/v1/report/add"),
         | 
| 33 35 | 
             
                    {
         | 
| 34 36 | 
             
                      :status   => elements[:status],
         | 
| @@ -39,26 +41,29 @@ module Houcho::CI | |
| 39 41 | 
             
                      :vc_log   => elements[:vc_log],
         | 
| 40 42 | 
             
                      :body     => elements[:body],
         | 
| 41 43 | 
             
                    }
         | 
| 42 | 
            -
                  ) | 
| 44 | 
            +
                  )
         | 
| 45 | 
            +
                  response.body
         | 
| 43 46 | 
             
                end
         | 
| 44 47 | 
             
              end
         | 
| 45 48 |  | 
| 46 49 | 
             
              class IkachanClient
         | 
| 47 50 | 
             
                def initialize(channel, server, port = 4979)
         | 
| 48 | 
            -
                  @ikachan_server | 
| 51 | 
            +
                  @ikachan_server = server
         | 
| 49 52 | 
             
                  @ikachan_listen_port = port
         | 
| 50 | 
            -
                  @ikachan_channels | 
| 53 | 
            +
                  @ikachan_channels = channel.is_a?(Array) ? channel : [channel]
         | 
| 51 54 | 
             
                end
         | 
| 52 55 |  | 
| 56 | 
            +
                # return が @ikachan_channels の最後の要素だけになってるからどうにかする
         | 
| 53 57 | 
             
                def post(message)
         | 
| 54 58 | 
             
                  @ikachan_channels.each do |channel|
         | 
| 55 | 
            -
                    Net::HTTP.post_form(
         | 
| 59 | 
            +
                    response = Net::HTTP.post_form(
         | 
| 56 60 | 
             
                      URI.parse("http://#{@ikachan_server}:#{@ikachan_listen_port}/notice"),
         | 
| 57 61 | 
             
                      {
         | 
| 58 62 | 
             
                        :channel => channel,
         | 
| 59 63 | 
             
                        :message => message,
         | 
| 60 64 | 
             
                      }
         | 
| 61 | 
            -
                    ) | 
| 65 | 
            +
                    )
         | 
| 66 | 
            +
                    response.body
         | 
| 62 67 | 
             
                  end
         | 
| 63 68 | 
             
                end
         | 
| 64 69 | 
             
              end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            require "thor"
         | 
| 2 | 
            +
            require "houcho/attribute"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Houcho
         | 
| 5 | 
            +
              module CLI
         | 
| 6 | 
            +
                class Attribute < Thor
         | 
| 7 | 
            +
                  namespace :attr
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def self.target_type_obj(target_type)
         | 
| 11 | 
            +
                    case target_type
         | 
| 12 | 
            +
                    when "role"
         | 
| 13 | 
            +
                      Houcho::Role.new
         | 
| 14 | 
            +
                    when "outerrole"
         | 
| 15 | 
            +
                      Houcho::OuterRole.new
         | 
| 16 | 
            +
                    when "host"
         | 
| 17 | 
            +
                      Houcho::Host.new
         | 
| 18 | 
            +
                    else
         | 
| 19 | 
            +
                      Houcho::CLI::Main.empty_args(self, shell, __method__)
         | 
| 20 | 
            +
                      # puts helps and exit(1)
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
                  desc "set", "set attribute"
         | 
| 26 | 
            +
                  option :target, :type => :hash, :required => true, :desc => "assign target of hash"
         | 
| 27 | 
            +
                  option :value, :type => :hash, :required => true, :desc => "assign attribute of hash"
         | 
| 28 | 
            +
                  option :force, :type => :boolean, :desc => "update attribute if defined already"
         | 
| 29 | 
            +
                  def set
         | 
| 30 | 
            +
                    options[:target].each do |target_type, target_name|
         | 
| 31 | 
            +
                      obj = Houcho::CLI::Attribute.target_type_obj(target_type)
         | 
| 32 | 
            +
                      begin
         | 
| 33 | 
            +
                        if options[:force]
         | 
| 34 | 
            +
                          obj.set_attr!(target_name, options[:value])
         | 
| 35 | 
            +
                        else
         | 
| 36 | 
            +
                          obj.set_attr(target_name, options[:value])
         | 
| 37 | 
            +
                        end
         | 
| 38 | 
            +
                      rescue Houcho::AttributeExceptiotn=> e
         | 
| 39 | 
            +
                        puts e.message
         | 
| 40 | 
            +
                        exit!
         | 
| 41 | 
            +
                      end
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
             | 
| 46 | 
            +
                  desc "get [attr name](optional)", "get attribute"
         | 
| 47 | 
            +
                  option :target, :type => :hash, :required => true, :desc => "assign target of hash"
         | 
| 48 | 
            +
                  def get(attr_name = nil)
         | 
| 49 | 
            +
                    options[:target].each do |target_type, target_name|
         | 
| 50 | 
            +
                      obj = Houcho::CLI::Attribute.target_type_obj(target_type)
         | 
| 51 | 
            +
                      obj.get_attr(target_name, attr_name).each do |k,v|
         | 
| 52 | 
            +
                        puts "#{k.to_s.color(:red)}:#{v}"
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
             | 
| 58 | 
            +
                  desc "delete [attr name](optional)", "delete attribute of host"
         | 
| 59 | 
            +
                  option :target, :type => :hash, :required => true, :desc => "assign target of hash"
         | 
| 60 | 
            +
                  def delete(attr_name = nil)
         | 
| 61 | 
            +
                    options[:target].each do |target_type, target_name|
         | 
| 62 | 
            +
                      obj = Houcho::CLI::Attribute.target_type_obj(target_type)
         | 
| 63 | 
            +
                      obj.del_attr(target_name, attr_name).each do |k,v|
         | 
| 64 | 
            +
                        print "#{k}:#{v} "
         | 
| 65 | 
            +
                      end
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            require 'thor'
         | 
| 2 | 
            +
            require 'houcho/host'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Houcho
         | 
| 5 | 
            +
              module CLI
         | 
| 6 | 
            +
                class Host < Thor
         | 
| 7 | 
            +
                  namespace :host
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  @@h = Houcho::Host.new
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  desc 'list', 'show all of host list'
         | 
| 12 | 
            +
                  def list
         | 
| 13 | 
            +
                    puts @@h.list.sort.join("\n")
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
             | 
| 17 | 
            +
                  desc 'attach [host1 host2 host3...] --roles [role1 role2...]', 'attach host to role'
         | 
| 18 | 
            +
                  option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 19 | 
            +
                  def attach(*args)
         | 
| 20 | 
            +
                    Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
         | 
| 21 | 
            +
                    @@h.attach(args, options[:roles])
         | 
| 22 | 
            +
                  rescue RoleExistenceException, SpecFileException, SQLite3::ConstraintException => e
         | 
| 23 | 
            +
                    puts e.message
         | 
| 24 | 
            +
                    exit!
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
             | 
| 28 | 
            +
                  desc 'detach [spec1 spec2 spec3...] --roles [role1 role2...]', 'detach spec from spec'
         | 
| 29 | 
            +
                  option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 30 | 
            +
                  def detach(*args)
         | 
| 31 | 
            +
                    Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
         | 
| 32 | 
            +
                    @@h.detach(args, options[:roles])
         | 
| 33 | 
            +
                  rescue RoleExistenceException, SQLite3::ConstraintException => e
         | 
| 34 | 
            +
                    puts e.message
         | 
| 35 | 
            +
                    exit!
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
                  desc 'details [spec1 spec2 spec3...]', 'show details about spec'
         | 
| 40 | 
            +
                  def details(*args)
         | 
| 41 | 
            +
                    Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
         | 
| 42 | 
            +
                    Houcho::CLI::Main.puts_details(@@h.details(args))
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            require 'thor'
         | 
| 2 | 
            +
            require 'houcho/outerrole'
         | 
| 3 | 
            +
            require 'houcho/outerrole/cloudforecast'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Houcho
         | 
| 6 | 
            +
              module CLI
         | 
| 7 | 
            +
                class OuterRole < Thor
         | 
| 8 | 
            +
                  namespace :host
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  @@or = Houcho::OuterRole.new
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  desc 'list', 'show all of host list'
         | 
| 13 | 
            +
                  def list
         | 
| 14 | 
            +
                    puts @@or.list.sort.join("\n")
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
             | 
| 18 | 
            +
                  desc 'attach [outerrole1 outerrole2 outerrole3...] --roles [role1 role2...]', 'attach outer role to role'
         | 
| 19 | 
            +
                  option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 20 | 
            +
                  def attach(*args)
         | 
| 21 | 
            +
                    Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
         | 
| 22 | 
            +
                    @@or.attach(args, options[:roles])
         | 
| 23 | 
            +
                  rescue RoleExistenceException, SpecFileException, SQLite3::ConstraintException => e
         | 
| 24 | 
            +
                    puts e.message
         | 
| 25 | 
            +
                    exit!
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
             | 
| 29 | 
            +
                  desc 'detach [outerrole1 outerrole2 outerrole3...] --roles [role1 role2...]', 'detach outer role from role'
         | 
| 30 | 
            +
                  option :roles, :type => :array, :required => true, :desc => 'specify the roles separated by spaces.'
         | 
| 31 | 
            +
                  def detach(*args)
         | 
| 32 | 
            +
                    Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
         | 
| 33 | 
            +
                    @@or.detach(args, options[:roles])
         | 
| 34 | 
            +
                  rescue RoleExistenceException, SQLite3::ConstraintException => e
         | 
| 35 | 
            +
                    puts e.message
         | 
| 36 | 
            +
                    exit!
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 40 | 
            +
                  desc 'details [outerrole1 outerrole2 outerrole3...]', 'show details about outerrole'
         | 
| 41 | 
            +
                  def details(*args)
         | 
| 42 | 
            +
                    Houcho::CLI::Main.empty_args(self, shell, __method__) if args.empty?
         | 
| 43 | 
            +
                    Houcho::CLI::Main.puts_details(@@or.details(args))
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
             | 
| 47 | 
            +
                  desc 'load', 'load role data from outer system'
         | 
| 48 | 
            +
                  def load
         | 
| 49 | 
            +
                    Houcho::OuterRole::CloudForecast.load
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         |