tinet 0.0.2
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 +7 -0
 - data/.gitignore +50 -0
 - data/.rspec +3 -0
 - data/CHANGELOG.md +11 -0
 - data/Gemfile +4 -0
 - data/LICENSE +21 -0
 - data/README.md +40 -0
 - data/Rakefile +6 -0
 - data/bin/tinet +5 -0
 - data/lib/tinet.rb +8 -0
 - data/lib/tinet/cli.rb +119 -0
 - data/lib/tinet/command/base.rb +130 -0
 - data/lib/tinet/command/build.rb +11 -0
 - data/lib/tinet/command/conf.rb +25 -0
 - data/lib/tinet/command/down.rb +43 -0
 - data/lib/tinet/command/exec.rb +18 -0
 - data/lib/tinet/command/init.rb +17 -0
 - data/lib/tinet/command/ps.rb +28 -0
 - data/lib/tinet/command/pull.rb +16 -0
 - data/lib/tinet/command/up.rb +104 -0
 - data/lib/tinet/data.rb +54 -0
 - data/lib/tinet/link.rb +65 -0
 - data/lib/tinet/node.rb +65 -0
 - data/lib/tinet/setting.rb +54 -0
 - data/lib/tinet/shell.rb +36 -0
 - data/lib/tinet/switch.rb +53 -0
 - data/lib/tinet/version.rb +3 -0
 - data/spec.template.yml +39 -0
 - data/tinet.gemspec +32 -0
 - metadata +132 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: f3759871bec017bb9c62083793496f041da97ea833be5ff9ad337c11fdc50854
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0d61c7aff75feef1ec886e10fdb81a60ba54674fc933d757c63800e2df0081f4
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 007d93174d1823b979983739553f7626d9826dba2727270aef246dcbc99d87d46ecb4a00bdf70eebdf7b86fe21fc8eea3429f5ff25399441ff788f58b4d23a78
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 5748d97ecbe6812c4bca50dee08b1b0f915f461dfcca5df178e1ba3680000d1205f5ff8f27b0aa898c44043af288047f69b26debbeaae559c8c512652f824afa
         
     | 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            *.gem
         
     | 
| 
      
 2 
     | 
    
         
            +
            *.rbc
         
     | 
| 
      
 3 
     | 
    
         
            +
            /.config
         
     | 
| 
      
 4 
     | 
    
         
            +
            /coverage/
         
     | 
| 
      
 5 
     | 
    
         
            +
            /InstalledFiles
         
     | 
| 
      
 6 
     | 
    
         
            +
            /pkg/
         
     | 
| 
      
 7 
     | 
    
         
            +
            /spec/reports/
         
     | 
| 
      
 8 
     | 
    
         
            +
            /spec/examples.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
            /test/tmp/
         
     | 
| 
      
 10 
     | 
    
         
            +
            /test/version_tmp/
         
     | 
| 
      
 11 
     | 
    
         
            +
            /tmp/
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            # Used by dotenv library to load environment variables.
         
     | 
| 
      
 14 
     | 
    
         
            +
            # .env
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ## Specific to RubyMotion:
         
     | 
| 
      
 17 
     | 
    
         
            +
            .dat*
         
     | 
| 
      
 18 
     | 
    
         
            +
            .repl_history
         
     | 
| 
      
 19 
     | 
    
         
            +
            build/
         
     | 
| 
      
 20 
     | 
    
         
            +
            *.bridgesupport
         
     | 
| 
      
 21 
     | 
    
         
            +
            build-iPhoneOS/
         
     | 
| 
      
 22 
     | 
    
         
            +
            build-iPhoneSimulator/
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            ## Specific to RubyMotion (use of CocoaPods):
         
     | 
| 
      
 25 
     | 
    
         
            +
            #
         
     | 
| 
      
 26 
     | 
    
         
            +
            # We recommend against adding the Pods directory to your .gitignore. However
         
     | 
| 
      
 27 
     | 
    
         
            +
            # you should judge for yourself, the pros and cons are mentioned at:
         
     | 
| 
      
 28 
     | 
    
         
            +
            # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
         
     | 
| 
      
 29 
     | 
    
         
            +
            #
         
     | 
| 
      
 30 
     | 
    
         
            +
            # vendor/Pods/
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            ## Documentation cache and generated files:
         
     | 
| 
      
 33 
     | 
    
         
            +
            /.yardoc/
         
     | 
| 
      
 34 
     | 
    
         
            +
            /_yardoc/
         
     | 
| 
      
 35 
     | 
    
         
            +
            /doc/
         
     | 
| 
      
 36 
     | 
    
         
            +
            /rdoc/
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            ## Environment normalization:
         
     | 
| 
      
 39 
     | 
    
         
            +
            /.bundle/
         
     | 
| 
      
 40 
     | 
    
         
            +
            /vendor/bundle
         
     | 
| 
      
 41 
     | 
    
         
            +
            /lib/bundler/man/
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            # for a library or gem, you might want to ignore these files since the code is
         
     | 
| 
      
 44 
     | 
    
         
            +
            # intended to run in multiple environments; otherwise, check them in:
         
     | 
| 
      
 45 
     | 
    
         
            +
            # Gemfile.lock
         
     | 
| 
      
 46 
     | 
    
         
            +
            # .ruby-version
         
     | 
| 
      
 47 
     | 
    
         
            +
            # .ruby-gemset
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
         
     | 
| 
      
 50 
     | 
    
         
            +
            .rvmrc
         
     | 
    
        data/.rspec
    ADDED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2019 Koki Sato
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 13 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # tinet-rb
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Ruby implement of [slankdev/tinet](https://github.com/slankdev/tinet).
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            :warning: **This is now prototype version. And also it is incompatible with YAML config format in [slankdev/tinet](https://github.com/slankdev/tinet).**
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ## Requirements
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            - Docker
         
     | 
| 
      
 10 
     | 
    
         
            +
            - Open vSwitch
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## Install
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            ```
         
     | 
| 
      
 15 
     | 
    
         
            +
            $ gem install tinet
         
     | 
| 
      
 16 
     | 
    
         
            +
            ```
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            ```
         
     | 
| 
      
 21 
     | 
    
         
            +
            $ tinet [OPTIONS] COMMAND
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Options:
         
     | 
| 
      
 24 
     | 
    
         
            +
              -f, [--specfile=SPECFILE]  # Specify specification YAML file (Default: ./spec.yml)
         
     | 
| 
      
 25 
     | 
    
         
            +
              -d, [--dry-run]            # Print the recipes that are needed to execute
         
     | 
| 
      
 26 
     | 
    
         
            +
              -v, [--version]            # Show the TINET version information
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            Commands:
         
     | 
| 
      
 29 
     | 
    
         
            +
              tinet build [OPTIONS]              # Build Docker images from the spec file
         
     | 
| 
      
 30 
     | 
    
         
            +
              tinet conf [OPTIONS]               # Execute commands in a running container
         
     | 
| 
      
 31 
     | 
    
         
            +
              tinet down [OPTIONS]               # Stop and remove containers
         
     | 
| 
      
 32 
     | 
    
         
            +
              tinet exec [OPTIONS] NODE COMMAND  # Execute a command in a running container
         
     | 
| 
      
 33 
     | 
    
         
            +
              tinet help [COMMAND]               # Describe available commands or one specific command
         
     | 
| 
      
 34 
     | 
    
         
            +
              tinet init                         # Generate template spec file
         
     | 
| 
      
 35 
     | 
    
         
            +
              tinet ps [OPTIONS]                 # List services
         
     | 
| 
      
 36 
     | 
    
         
            +
              tinet pull [OPTIONS]               # Pull service images
         
     | 
| 
      
 37 
     | 
    
         
            +
              tinet restart [OPTIONS]            # Down and Up running containers
         
     | 
| 
      
 38 
     | 
    
         
            +
              tinet up [OPTIONS]                 # Create and start containers
         
     | 
| 
      
 39 
     | 
    
         
            +
              tinet version                      # Show the TINET version information
         
     | 
| 
      
 40 
     | 
    
         
            +
            ```
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/tinet
    ADDED
    
    
    
        data/lib/tinet.rb
    ADDED
    
    
    
        data/lib/tinet/cli.rb
    ADDED
    
    | 
         @@ -0,0 +1,119 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "thor"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tinet/setting"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tinet/command/build"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "tinet/command/conf"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "tinet/command/down"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "tinet/command/exec"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "tinet/command/init"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "tinet/command/ps"
         
     | 
| 
      
 9 
     | 
    
         
            +
            require "tinet/command/pull"
         
     | 
| 
      
 10 
     | 
    
         
            +
            require "tinet/command/up"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 13 
     | 
    
         
            +
              class CLI < Thor
         
     | 
| 
      
 14 
     | 
    
         
            +
                map %w[--version -v] => :version
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                desc 'init', 'Generate template spec file'
         
     | 
| 
      
 17 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 18 
     | 
    
         
            +
                def init
         
     | 
| 
      
 19 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Tinet::Command::Init.new.run
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                desc 'ps [OPTIONS]', 'List services'
         
     | 
| 
      
 24 
     | 
    
         
            +
                option :all, aliases: '-a', type: :boolean, desc: 'Show all containers (default shows just running)'
         
     | 
| 
      
 25 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 26 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 27 
     | 
    
         
            +
                def ps
         
     | 
| 
      
 28 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Tinet::Command::Ps.new(options).run
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                desc 'up [OPTIONS]', 'Create and start containers'
         
     | 
| 
      
 33 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 34 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 35 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 36 
     | 
    
         
            +
                def up
         
     | 
| 
      
 37 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  Tinet::Command::Up.new(options).run
         
     | 
| 
      
 39 
     | 
    
         
            +
                  Tinet::Command::Conf.new(options).run
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                desc 'down [OPTIONS]', 'Stop and remove containers'
         
     | 
| 
      
 43 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 44 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 45 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 46 
     | 
    
         
            +
                def down
         
     | 
| 
      
 47 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 48 
     | 
    
         
            +
                  Tinet::Command::Down.new(options).run
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                desc 'pull [OPTIONS]', 'Pull service images'
         
     | 
| 
      
 52 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 53 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 54 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 55 
     | 
    
         
            +
                def pull
         
     | 
| 
      
 56 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  Tinet::Command::Pull.new(options).run
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                desc 'exec [OPTIONS] NODE COMMAND', 'Execute a command in a running container'
         
     | 
| 
      
 61 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 62 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 63 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 64 
     | 
    
         
            +
                def exec(node, command)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 66 
     | 
    
         
            +
                  Tinet::Command::Exec.new(options).run(node, command)
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                desc 'build [OPTIONS]', 'Build Docker images from the spec file'
         
     | 
| 
      
 70 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 71 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 72 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 73 
     | 
    
         
            +
                def build
         
     | 
| 
      
 74 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 75 
     | 
    
         
            +
                  Tinet::Command::Build.new(options).run
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                desc 'conf [OPTIONS]', 'Execute commands in a running container'
         
     | 
| 
      
 79 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 80 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 81 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 82 
     | 
    
         
            +
                def conf
         
     | 
| 
      
 83 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 84 
     | 
    
         
            +
                  Tinet::Command::Conf.new(options).run
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                desc 'restart [OPTIONS]', 'Down and Up running containers'
         
     | 
| 
      
 88 
     | 
    
         
            +
                option :specfile, aliases: '-f', type: :string, default: Tinet::DEFAULT_SPECFILE_PATH, desc: 'Specify specification YAML file'
         
     | 
| 
      
 89 
     | 
    
         
            +
                option 'dry-run', aliases: '-d', type: :boolean, default: false, desc: 'Print the recipes that are needed to execute'
         
     | 
| 
      
 90 
     | 
    
         
            +
                option :version, aliases: '-v', type: :boolean, default: false, desc: 'Show the TINET version information'
         
     | 
| 
      
 91 
     | 
    
         
            +
                def restart
         
     | 
| 
      
 92 
     | 
    
         
            +
                  return version if options[:version]
         
     | 
| 
      
 93 
     | 
    
         
            +
                  Tinet::Command::Down.new(options).run
         
     | 
| 
      
 94 
     | 
    
         
            +
                  Tinet::Command::Up.new(options).run
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                desc 'version', 'Show the TINET version information'
         
     | 
| 
      
 98 
     | 
    
         
            +
                def version
         
     | 
| 
      
 99 
     | 
    
         
            +
                  puts "TINET version: #{Tinet::VERSION}"
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                # @note Override {Thor#help}
         
     | 
| 
      
 103 
     | 
    
         
            +
                def help(command = nil, subcommand = false)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  if command.nil?
         
     | 
| 
      
 105 
     | 
    
         
            +
                    puts <<-USAGE
         
     | 
| 
      
 106 
     | 
    
         
            +
            Usage:
         
     | 
| 
      
 107 
     | 
    
         
            +
              tinet [OPTIONS] COMMAND
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            Options:
         
     | 
| 
      
 110 
     | 
    
         
            +
              -f, [--specfile=SPECFILE]  # Specify specification YAML file (Default: ./spec.yml)
         
     | 
| 
      
 111 
     | 
    
         
            +
              -d, [--dry-run]            # Print the recipes that are needed to execute
         
     | 
| 
      
 112 
     | 
    
         
            +
              -v, [--version]            # Show the TINET version information
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            USAGE
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  super
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
              end
         
     | 
| 
      
 119 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,130 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/data"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tinet/link"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tinet/shell"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 8 
     | 
    
         
            +
                  include Shell
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(options = {})
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @options = options
         
     | 
| 
      
 12 
     | 
    
         
            +
                    check_docker_installed unless dry_run
         
     | 
| 
      
 13 
     | 
    
         
            +
                    check_ovs_vsctl_installed unless dry_run
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  # @return [Logger]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def logger
         
     | 
| 
      
 20 
     | 
    
         
            +
                    Tinet.logger
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  # @return [String]
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def specfile
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @options.fetch(:specfile, '')
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  # @return [boolean]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def dry_run
         
     | 
| 
      
 30 
     | 
    
         
            +
                    @options.fetch('dry-run', false)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  # @return [Tinet::Data, nil]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  def data
         
     | 
| 
      
 35 
     | 
    
         
            +
                    return nil if specfile.nil? || specfile.empty?
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @data ||= Tinet::Data.parse(specfile)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  # @return [Array<Tinet::Node>, nil]
         
     | 
| 
      
 40 
     | 
    
         
            +
                  def nodes
         
     | 
| 
      
 41 
     | 
    
         
            +
                    data.nodes unless data.nil?
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  # @return [Array<Tinet::Switch>, nil]
         
     | 
| 
      
 45 
     | 
    
         
            +
                  def switches
         
     | 
| 
      
 46 
     | 
    
         
            +
                    data.switches unless data.nil?
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  # @return [Array<Tinet::Link>]
         
     | 
| 
      
 50 
     | 
    
         
            +
                  def links
         
     | 
| 
      
 51 
     | 
    
         
            +
                    return nil if data.nil?
         
     | 
| 
      
 52 
     | 
    
         
            +
                    @links ||= Tinet::Link.link(nodes, switches)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  # @param name [String]
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # @return [String]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def namespaced(name)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    "#{Tinet.namespace}-#{name}"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  # @note Override {Tinet::Shell#sh}
         
     | 
| 
      
 62 
     | 
    
         
            +
                  def sh(command, dry_run: dry_run(), print: true, continue: false)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    super
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def mount_docker_netns(container, netns)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    if dry_run
         
     | 
| 
      
 68 
     | 
    
         
            +
                      logger.info "PID=`sudo docker inspect #{container} -f {{.State.Pid}}`"
         
     | 
| 
      
 69 
     | 
    
         
            +
                      pid = '$PID'
         
     | 
| 
      
 70 
     | 
    
         
            +
                    else
         
     | 
| 
      
 71 
     | 
    
         
            +
                      pid, * = sudo "docker inspect #{container} -f {{.State.Pid}}"
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                    sudo 'mkdir -p /var/run/netns'
         
     | 
| 
      
 74 
     | 
    
         
            +
                    sudo "ln -s /proc/#{pid}/ns/net /var/run/netns/#{netns}"
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  def exec_pre_cmd
         
     | 
| 
      
 78 
     | 
    
         
            +
                    data.options[:pre_cmd].each { |cmd| sudo command }
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  def exec_pre_init
         
     | 
| 
      
 82 
     | 
    
         
            +
                    data.options[:pre_init].each { |cmd| sudo command }
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  def exec_post_init
         
     | 
| 
      
 86 
     | 
    
         
            +
                    data.options[:post_init].each { |cmd| sudo command }
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  def exec_pre_conf
         
     | 
| 
      
 90 
     | 
    
         
            +
                    data.options[:pre_conf].each { |cmd| sudo command }
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  def exec_post_conf
         
     | 
| 
      
 94 
     | 
    
         
            +
                    data.options[:post_conf].each { |cmd| sudo command }
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  def exec_pre_down
         
     | 
| 
      
 98 
     | 
    
         
            +
                    data.options[:pre_down].each { |cmd| sudo command }
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  def exec_post_down
         
     | 
| 
      
 102 
     | 
    
         
            +
                    data.options[:post_down].each { |cmd| sudo command }
         
     | 
| 
      
 103 
     | 
    
         
            +
                  end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  private
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  # @return [boolean]
         
     | 
| 
      
 108 
     | 
    
         
            +
                  def command_exist?(command)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    *, status = sh "which #{command}", print: false, continue: true
         
     | 
| 
      
 110 
     | 
    
         
            +
                    status.success?
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                  def check_docker_installed
         
     | 
| 
      
 114 
     | 
    
         
            +
                    unless command_exist?('docker')
         
     | 
| 
      
 115 
     | 
    
         
            +
                      message = 'ERROR: Docker is not installed. TINET requires Docker.'
         
     | 
| 
      
 116 
     | 
    
         
            +
                      logger.error(message)
         
     | 
| 
      
 117 
     | 
    
         
            +
                      exit(1)
         
     | 
| 
      
 118 
     | 
    
         
            +
                    end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                  def check_ovs_vsctl_installed
         
     | 
| 
      
 122 
     | 
    
         
            +
                    unless command_exist?('ovs-vsctl')
         
     | 
| 
      
 123 
     | 
    
         
            +
                      message = 'ERROR: Open vSwitch is not installed. TINET requires Open vSwitch.'
         
     | 
| 
      
 124 
     | 
    
         
            +
                      logger.error(message)
         
     | 
| 
      
 125 
     | 
    
         
            +
                      exit(1)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Conf < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 7 
     | 
    
         
            +
                    exec_pre_cmd
         
     | 
| 
      
 8 
     | 
    
         
            +
                    exec_pre_conf
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 11 
     | 
    
         
            +
                      node.cmds.each do |cmd|
         
     | 
| 
      
 12 
     | 
    
         
            +
                        case node.type
         
     | 
| 
      
 13 
     | 
    
         
            +
                        when :docker
         
     | 
| 
      
 14 
     | 
    
         
            +
                          sudo "docker exec #{namespaced(node.name)} #{cmd} > /dev/null"
         
     | 
| 
      
 15 
     | 
    
         
            +
                        when :netns
         
     | 
| 
      
 16 
     | 
    
         
            +
                          sudo "ip netns exec #{namespaced(node.name)} #{cmd} > /dev/null"
         
     | 
| 
      
 17 
     | 
    
         
            +
                        end
         
     | 
| 
      
 18 
     | 
    
         
            +
                      end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    exec_post_conf
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Down < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 7 
     | 
    
         
            +
                    exec_pre_cmd
         
     | 
| 
      
 8 
     | 
    
         
            +
                    exec_pre_down
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 11 
     | 
    
         
            +
                      node.interfaces.each do |interface|
         
     | 
| 
      
 12 
     | 
    
         
            +
                        if interface.type == :phys
         
     | 
| 
      
 13 
     | 
    
         
            +
                          detach_physnet_from_docker("#{namespaced(node.name)}", interface.name)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        end
         
     | 
| 
      
 15 
     | 
    
         
            +
                      end
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      case node.type
         
     | 
| 
      
 20 
     | 
    
         
            +
                      when :docker
         
     | 
| 
      
 21 
     | 
    
         
            +
                        sudo "docker stop #{namespaced(node.name)}"
         
     | 
| 
      
 22 
     | 
    
         
            +
                      when :netns
         
     | 
| 
      
 23 
     | 
    
         
            +
                        sudo "ip netns del #{namespaced(node.name)}"
         
     | 
| 
      
 24 
     | 
    
         
            +
                      end
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    switches.each do |switch|
         
     | 
| 
      
 28 
     | 
    
         
            +
                      sudo "ovs-vsctl del-br #{namespaced(switch.name)}"
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    exec_post_down
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  private
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def detach_physnet_from_docker(container, ifname)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    mount_docker_netns(container, container)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    sudo "ip netns exec #{container} ip link set #{ifname} netns 1"
         
     | 
| 
      
 39 
     | 
    
         
            +
                    sudo "ip netns del #{container}"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Exec < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def run(node_name, command)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    node = nodes.find { |node| node.name == node_name }
         
     | 
| 
      
 8 
     | 
    
         
            +
                    raise "No such container: #{node_name}" if node.nil?
         
     | 
| 
      
 9 
     | 
    
         
            +
                    case node.type
         
     | 
| 
      
 10 
     | 
    
         
            +
                    when :docker
         
     | 
| 
      
 11 
     | 
    
         
            +
                      sudo "docker exec -it #{namespaced(node.name)} #{command}"
         
     | 
| 
      
 12 
     | 
    
         
            +
                    when :netns
         
     | 
| 
      
 13 
     | 
    
         
            +
                      sudo "ip netns exec #{namespaced(node.name)} #{command}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "fileutils"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tinet/setting"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tinet/shell"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Init < Base
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 10 
     | 
    
         
            +
                    template = File.join(Tinet::ROOT, 'spec.template.yml')
         
     | 
| 
      
 11 
     | 
    
         
            +
                    specfile = Tinet::DEFAULT_SPECFILE_PATH
         
     | 
| 
      
 12 
     | 
    
         
            +
                    FileUtils.cp(template, specfile)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    logger.info 'Initialized. Check spec.yml'
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Ps < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 7 
     | 
    
         
            +
                    if all
         
     | 
| 
      
 8 
     | 
    
         
            +
                      stdout, * = sudo "docker ps -a -f name=#{Tinet.namespace}"
         
     | 
| 
      
 9 
     | 
    
         
            +
                    else
         
     | 
| 
      
 10 
     | 
    
         
            +
                      stdout, * = sudo "docker ps -f name=#{Tinet.namespace}"
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    unless dry_run
         
     | 
| 
      
 14 
     | 
    
         
            +
                      logger.info 'TINET Docker Containers'
         
     | 
| 
      
 15 
     | 
    
         
            +
                      logger.info '-' * 50
         
     | 
| 
      
 16 
     | 
    
         
            +
                      logger.info stdout
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  private
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  # @return [boolean]
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def all
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @options[:all]
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Pull < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 7 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 8 
     | 
    
         
            +
                      unless node.image.nil?
         
     | 
| 
      
 9 
     | 
    
         
            +
                        stdout, * = sudo "docker pull #{node.image}"
         
     | 
| 
      
 10 
     | 
    
         
            +
                        logger.info stdout unless dry_run
         
     | 
| 
      
 11 
     | 
    
         
            +
                      end
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,104 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "tinet/command/base"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Up < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 7 
     | 
    
         
            +
                    exec_pre_cmd
         
     | 
| 
      
 8 
     | 
    
         
            +
                    exec_pre_init
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    # Create Nodes and Switches
         
     | 
| 
      
 11 
     | 
    
         
            +
                    nodes.each { |node| node_up(node) }
         
     | 
| 
      
 12 
     | 
    
         
            +
                    switches.each { |switch| switch_up(switch) }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    # Create Links
         
     | 
| 
      
 15 
     | 
    
         
            +
                    links.each { |link| link_up(link) }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    # Attach physnet / veth to Conitaner
         
     | 
| 
      
 18 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      node.interfaces.each do |interface|
         
     | 
| 
      
 20 
     | 
    
         
            +
                        case interface.type
         
     | 
| 
      
 21 
     | 
    
         
            +
                        when :phys
         
     | 
| 
      
 22 
     | 
    
         
            +
                          koko_physnet("#{namespaced(node.name)}", interface.name)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        when :veth
         
     | 
| 
      
 24 
     | 
    
         
            +
                          sudo "ip link add #{interface.name} type veth peer name #{interface.args}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                          koko_physnet("#{namespaced(node.name)}", interface.name)
         
     | 
| 
      
 26 
     | 
    
         
            +
                          sudo "ip link set #{interface.args} up"
         
     | 
| 
      
 27 
     | 
    
         
            +
                        end
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    exec_post_init
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  private
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def all
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @options[:all]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  # @param node [Tinet::Node]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def node_up(node)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    case node.type
         
     | 
| 
      
 43 
     | 
    
         
            +
                    when :docker
         
     | 
| 
      
 44 
     | 
    
         
            +
                      sudo "docker run -td --hostname #{node.name} --net=none --name #{namespaced(node.name)} --rm --privileged #{node.image}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    when :netns
         
     | 
| 
      
 46 
     | 
    
         
            +
                      sudo "ip netns add #{namespaced(node.name)}"
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  # @param switch [Tinet::Switch]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  def switch_up(switch)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    sudo "ovs-vsctl add-br #{namespaced(switch.name)}"
         
     | 
| 
      
 53 
     | 
    
         
            +
                    sudo "ip link set #{namespaced(switch.name)} up"
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  # @param link [Tinet::Link]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def link_up(link)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    left, right = link.left, link.right
         
     | 
| 
      
 59 
     | 
    
         
            +
                    case link.type
         
     | 
| 
      
 60 
     | 
    
         
            +
                    when :n2n
         
     | 
| 
      
 61 
     | 
    
         
            +
                      mount_docker_netns(namespaced(left.node.name), namespaced(left.node.name)) if left.node.type == :docker
         
     | 
| 
      
 62 
     | 
    
         
            +
                      mount_docker_netns(namespaced(right.node.name), namespaced(right.node.name)) if right.node.type == :docker
         
     | 
| 
      
 63 
     | 
    
         
            +
                      sudo "ip link add #{left.name} netns #{namespaced(left.node.name)} type veth peer name #{right.name} netns #{namespaced(right.node.name)}"
         
     | 
| 
      
 64 
     | 
    
         
            +
                      sudo "ip netns exec #{namespaced(left.node.name)} ip link set #{left.name} up"
         
     | 
| 
      
 65 
     | 
    
         
            +
                      sudo "ip netns exec #{namespaced(right.node.name)} ip link set #{right.name} up"
         
     | 
| 
      
 66 
     | 
    
         
            +
                      sudo "ip netns del #{namespaced(left.node.name)}" if left.node.type == :docker
         
     | 
| 
      
 67 
     | 
    
         
            +
                      sudo "ip netns del #{namespaced(right.node.name)}" if right.node.type == :docker
         
     | 
| 
      
 68 
     | 
    
         
            +
                    when :s2n
         
     | 
| 
      
 69 
     | 
    
         
            +
                      case right.node.type
         
     | 
| 
      
 70 
     | 
    
         
            +
                      when :docker
         
     | 
| 
      
 71 
     | 
    
         
            +
                        kokobr(namespaced(left.switch.name), namespaced(right.node.name), right.name)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      when :netns
         
     | 
| 
      
 73 
     | 
    
         
            +
                        kokobr_netns(namespaced(left.switch.name), namespaced(right.node.name), right.name)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      end
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  def kokobr(bridge, container, ifname)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    mount_docker_netns(container, container)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    sudo "ip link add name #{ifname} type veth peer name #{container}-#{ifname}"
         
     | 
| 
      
 81 
     | 
    
         
            +
                    sudo "ip link set dev #{ifname} netns #{container}"
         
     | 
| 
      
 82 
     | 
    
         
            +
                    sudo "ip link set #{container}-#{ifname} up"
         
     | 
| 
      
 83 
     | 
    
         
            +
                    sudo "ip netns exec #{container} ip link set #{ifname} up"
         
     | 
| 
      
 84 
     | 
    
         
            +
                    sudo "ip netns del #{container}"
         
     | 
| 
      
 85 
     | 
    
         
            +
                    sudo "ovs-vsctl add-port #{bridge} #{container}-#{ifname}"
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  def kokobr_netns(bridge, container, ifname)
         
     | 
| 
      
 89 
     | 
    
         
            +
                    sudo "ip link add name #{ifname} type veth peer name #{container}-#{ifname}"
         
     | 
| 
      
 90 
     | 
    
         
            +
                    sudo "ip link set dev #{ifname} netns #{container}"
         
     | 
| 
      
 91 
     | 
    
         
            +
                    sudo "ip link set #{container}-#{ifname} up"
         
     | 
| 
      
 92 
     | 
    
         
            +
                    sudo "ip netns exec #{container} ip link set #{ifname} up"
         
     | 
| 
      
 93 
     | 
    
         
            +
                    sudo "ovs-vsctl add-port #{bridge} #{container}-#{ifname}"
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  def koko_physnet(container, netif)
         
     | 
| 
      
 97 
     | 
    
         
            +
                    mount_docker_netns(container, container)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    sudo "ip link set dev #{netif} netns #{container}"
         
     | 
| 
      
 99 
     | 
    
         
            +
                    sudo "ip netns exec #{container} ip link set #{netif} up"
         
     | 
| 
      
 100 
     | 
    
         
            +
                    sudo "ip netns del #{container}"
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tinet/data.rb
    ADDED
    
    | 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "yaml"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tinet/node"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tinet/switch"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Data
         
     | 
| 
      
 7 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @param yaml_path [String]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # @return [Tinet::Data]
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def parse(yaml_path)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    yaml = YAML.load_file(yaml_path)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    raise InvalidYAMLError, "Nodes must be array" unless yaml['nodes'].is_a?(Array)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    raise InvalidYAMLError, "Switches must be array" unless yaml['switches'].is_a?(Array)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    namespace = yaml.fetch('meta', {}).fetch('namespace', nil)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    Tinet.namespace = namespace unless namespace.nil? || namespace.empty?
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    nodes = yaml['nodes'].map { |node| Tinet::Node.parse(node) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                    switches = yaml['switches'].map { |switch| Tinet::Switch.parse(switch) }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 21 
     | 
    
         
            +
                      pre_cmd: fetch(yaml, 'pre_cmd'),
         
     | 
| 
      
 22 
     | 
    
         
            +
                      pre_init: fetch(yaml, 'pre_init'),
         
     | 
| 
      
 23 
     | 
    
         
            +
                      post_init: fetch(yaml, 'post_init'),
         
     | 
| 
      
 24 
     | 
    
         
            +
                      pre_conf: fetch(yaml, 'pre_conf'),
         
     | 
| 
      
 25 
     | 
    
         
            +
                      post_conf: fetch(yaml, 'post_conf'),
         
     | 
| 
      
 26 
     | 
    
         
            +
                      pre_down: fetch(yaml, 'pre_down'),
         
     | 
| 
      
 27 
     | 
    
         
            +
                      post_down: fetch(yaml, 'post_down')
         
     | 
| 
      
 28 
     | 
    
         
            +
                    }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    self.new(nodes, switches, options)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  private
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  # @param yaml [Hash]
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # @param key [String]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @return [Array<String>]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def fetch(yaml, key)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    yaml.fetch(key, {}).fetch('cmds', []).map { |cmd| cmd['cmd'] || cmd }
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                attr_reader :nodes, :switches, :options
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                # @param nodes [Array<Tinet::Node>]
         
     | 
| 
      
 46 
     | 
    
         
            +
                # @param switches [Array<Tinet::Switch>]
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @param options [Hash{Symbol => Array<String>}]
         
     | 
| 
      
 48 
     | 
    
         
            +
                def initialize(nodes, switches, options)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @nodes = nodes
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @switches = switches
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tinet/link.rb
    ADDED
    
    | 
         @@ -0,0 +1,65 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Link
         
     | 
| 
      
 3 
     | 
    
         
            +
                TYPES = %w(n2n s2n).freeze
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # @param nodes [Array<Tinet::Node>]
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # @param switches [Array<Tinet::Switch>]
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # @return [Array<Tinet::Link>]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def link(nodes, switches)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    link_n2n(nodes) + link_s2n(nodes, switches)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # @param nodes [Array<Tinet::Node>]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # @return [Array<Tinet::Link>]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  def link_n2n(nodes)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    list, index = [], {}
         
     | 
| 
      
 17 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 18 
     | 
    
         
            +
                      node.interfaces.each do |interface|
         
     | 
| 
      
 19 
     | 
    
         
            +
                        if interface.type == :direct
         
     | 
| 
      
 20 
     | 
    
         
            +
                          key = "#{interface.args}-#{node.name}##{interface.name}"  # example: C0#net0-C1#net0
         
     | 
| 
      
 21 
     | 
    
         
            +
                          if index.key?(key)
         
     | 
| 
      
 22 
     | 
    
         
            +
                            list << self.new(index[key], interface, :n2n)
         
     | 
| 
      
 23 
     | 
    
         
            +
                          else
         
     | 
| 
      
 24 
     | 
    
         
            +
                            key = "#{node.name}##{interface.name}-#{interface.args}"  # example: C1#net0-C0#net0
         
     | 
| 
      
 25 
     | 
    
         
            +
                            index[key] = interface
         
     | 
| 
      
 26 
     | 
    
         
            +
                          end
         
     | 
| 
      
 27 
     | 
    
         
            +
                        end
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    list
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  # @param nodes [Array<Tinet::Node>]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @param switches [Array<Tinet::Switch>]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @return [Array<Tinet::Link>]
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def link_s2n(nodes, switches)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    list, index = [], {}
         
     | 
| 
      
 38 
     | 
    
         
            +
                    nodes.each do |node|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      node.interfaces.each do |interface|
         
     | 
| 
      
 40 
     | 
    
         
            +
                        key = "#{node.name}-#{interface.args}"  # example: C0-B0
         
     | 
| 
      
 41 
     | 
    
         
            +
                        index[key] = interface if interface.type == :bridge
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    switches.each do |switch|
         
     | 
| 
      
 45 
     | 
    
         
            +
                      switch.interfaces.each do |interface|
         
     | 
| 
      
 46 
     | 
    
         
            +
                        key = "#{interface.args}-#{switch.name}"  # example: C0-B0
         
     | 
| 
      
 47 
     | 
    
         
            +
                        list << self.new(interface, index[key], :s2n) if index.key?(key)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      end
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    list
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                attr_reader :left, :right, :type
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                # @param left [Tinet::Node::Interfase, Tinet::Switch::Interfase]
         
     | 
| 
      
 57 
     | 
    
         
            +
                # @param right [Tinet::Node::Interfase]
         
     | 
| 
      
 58 
     | 
    
         
            +
                # @param type [Symbol]
         
     | 
| 
      
 59 
     | 
    
         
            +
                def initialize(left, right, type)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @left = left
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @right = right
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @type = type
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tinet/node.rb
    ADDED
    
    | 
         @@ -0,0 +1,65 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                TYPES = %w(docker netns).freeze
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                # @param node_hash [Hash]
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @return [Tinet::Node]
         
     | 
| 
      
 7 
     | 
    
         
            +
                def self.parse(node_hash)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  name, type, interfaces = node_hash['name'], node_hash['type'], node_hash['interfaces']
         
     | 
| 
      
 9 
     | 
    
         
            +
                  raise InvalidYAMLError, "Node name is missing" if name.nil? || name.empty?
         
     | 
| 
      
 10 
     | 
    
         
            +
                  raise InvalidTypeError, "Unknown node type: #{type}" unless TYPES.include?(type)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  raise InvalidYAMLError, "Node interfaces must be array" unless interfaces.is_a?(Array)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  interfaces = interfaces.map { |interface| Interfase.parse(interface) }
         
     | 
| 
      
 14 
     | 
    
         
            +
                  cmds = node_hash.fetch('cmds', []).map { |cmd| cmd['cmd'] || cmd }
         
     | 
| 
      
 15 
     | 
    
         
            +
                  self.new(name, type.to_sym, node_hash['image'], node_hash['build'], interfaces, cmds)
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                attr_reader :name, :type, :image, :build, :interfaces, :cmds
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                # @param name [String]
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @param type [Symbol]
         
     | 
| 
      
 22 
     | 
    
         
            +
                # @param image [String, nil]
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @param build [String, nil]
         
     | 
| 
      
 24 
     | 
    
         
            +
                # @param interfaces [Array<Tinet::Node::Interfase>]
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @param cmds [Array<String>]
         
     | 
| 
      
 26 
     | 
    
         
            +
                def initialize(name, type, image, build, interfaces, cmds)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @type = type
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @image = image
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @build = build
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @interfaces = interfaces
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @cmds = cmds
         
     | 
| 
      
 33 
     | 
    
         
            +
                  interfaces.each { |interface| interface.node = self }
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                class Interfase
         
     | 
| 
      
 37 
     | 
    
         
            +
                  TYPES = %w(direct bridge veth phys).freeze
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  # @param interface_hash [Hash]
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # @return [Tinet::Node::Interfase]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def self.parse(interface_hash)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    name, type, args = interface_hash['name'], interface_hash['type'], interface_hash['args']
         
     | 
| 
      
 43 
     | 
    
         
            +
                    raise InvalidYAMLError, "Interfase name is missing" if name.nil? || name.empty?
         
     | 
| 
      
 44 
     | 
    
         
            +
                    raise InvalidTypeError, "Unknown interface type: #{type}" unless TYPES.include?(type)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    self.new(name, type.to_sym, args)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  attr_reader :name, :type, :args, :node
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  # @param name [String]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # @param type [Symbol]
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # @param args [String, nil]
         
     | 
| 
      
 53 
     | 
    
         
            +
                  def initialize(name, type, args)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 55 
     | 
    
         
            +
                    @type = type.to_sym
         
     | 
| 
      
 56 
     | 
    
         
            +
                    @args = args
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @node = nil
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  def node=(node)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    @node = node
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "logger"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Setting
         
     | 
| 
      
 5 
     | 
    
         
            +
                ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
         
     | 
| 
      
 6 
     | 
    
         
            +
                DEFAULT_SPECFILE_PATH = './spec.yml'.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 9 
     | 
    
         
            +
                def root
         
     | 
| 
      
 10 
     | 
    
         
            +
                  ROOT
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 14 
     | 
    
         
            +
                def namespace
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @namespace ||= 'tinet'
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                # @param namespace [String]
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 20 
     | 
    
         
            +
                def namespace=(namespace)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @namespace = namespace
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # @return [Logger]
         
     | 
| 
      
 25 
     | 
    
         
            +
                def logger
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @logger ||= Logger.new($stderr).tap do |logger|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    logger.formatter = proc { |_sev, _dtm, _name, message| message + "\n" }
         
     | 
| 
      
 28 
     | 
    
         
            +
                    logger.level = Logger::INFO
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                # @param logger [Logger]
         
     | 
| 
      
 33 
     | 
    
         
            +
                # @return [Logger]
         
     | 
| 
      
 34 
     | 
    
         
            +
                def logger=(logger)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @logger = logger
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              SettingSingleton = Setting.new
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 42 
     | 
    
         
            +
                def const_missing(name)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  Setting.const_get name
         
     | 
| 
      
 44 
     | 
    
         
            +
                rescue NameError
         
     | 
| 
      
 45 
     | 
    
         
            +
                  super
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def method_missing(method, *args)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  SettingSingleton.__send__ method, *args
         
     | 
| 
      
 50 
     | 
    
         
            +
                rescue NoMethodError
         
     | 
| 
      
 51 
     | 
    
         
            +
                  super
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tinet/shell.rb
    ADDED
    
    | 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "open3"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "tinet/setting"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Shell
         
     | 
| 
      
 6 
     | 
    
         
            +
                DummyStatus = Struct.new(:success) do |status|
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def success?
         
     | 
| 
      
 8 
     | 
    
         
            +
                    success
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def sudo(command)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  sh "sudo #{command}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def sh(command, dry_run: false, print: false, continue: false)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  if dry_run || print
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Tinet.logger.info command
         
     | 
| 
      
 19 
     | 
    
         
            +
                  else
         
     | 
| 
      
 20 
     | 
    
         
            +
                    Tinet.logger.debug command
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  return ['', '', DummyStatus.new(true)] if dry_run
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  stdout, stderr, status = Open3.capture3(command)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  if !status.success? && !continue
         
     | 
| 
      
 28 
     | 
    
         
            +
                    Tinet.logger.error "Command '#{command}' failed:"
         
     | 
| 
      
 29 
     | 
    
         
            +
                    Tinet.logger.error "  #{stderr.chomp}" unless stderr.chomp.empty?
         
     | 
| 
      
 30 
     | 
    
         
            +
                    exit(status.to_i)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  [stdout.chomp, stderr.chomp, status]
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tinet/switch.rb
    ADDED
    
    | 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Tinet
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Switch
         
     | 
| 
      
 3 
     | 
    
         
            +
                # @param switch_hash [Hash]
         
     | 
| 
      
 4 
     | 
    
         
            +
                # @return [Tinet::Switch]
         
     | 
| 
      
 5 
     | 
    
         
            +
                def self.parse(switch_hash)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  name, interfaces = switch_hash['name'], switch_hash['interfaces']
         
     | 
| 
      
 7 
     | 
    
         
            +
                  raise InvalidYAMLError, "Switch name is missing" if name.nil? || name.empty?
         
     | 
| 
      
 8 
     | 
    
         
            +
                  raise InvalidYAMLError, "Switch interfaces must be array" unless interfaces.is_a?(Array)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  interfaces = interfaces.map { |interface| Interfase.parse(interface) }
         
     | 
| 
      
 11 
     | 
    
         
            +
                  self.new(name, interfaces)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :name, :interfaces
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # @param name [String]
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @param interfaces [Array<Tinet::Switch::Interfase>]
         
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(name, interfaces)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @interfaces = interfaces
         
     | 
| 
      
 21 
     | 
    
         
            +
                  interfaces.each { |interface| interface.switch = self }
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                class Interfase
         
     | 
| 
      
 25 
     | 
    
         
            +
                  TYPES = %w(docker netns phys).freeze
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  # @param interface_hash [Hash]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @return [Tinet::Switch::Interfase]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def self.parse(interface_hash)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    name, type, args = interface_hash['name'], interface_hash['type'], interface_hash['args']
         
     | 
| 
      
 31 
     | 
    
         
            +
                    raise InvalidYAMLError, "Interfase name is missing" if name.nil? || name.empty?
         
     | 
| 
      
 32 
     | 
    
         
            +
                    raise InvalidTypeError, "Unknown interface type: #{type}" unless TYPES.include?(type)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    self.new(name, type.to_sym, args)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  attr_reader :name, :type, :args, :switch
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  # @param name [String]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # @param type [Symbol]
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # @param args [String, nil]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def initialize(name, type, args)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @name = name
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @type = type.to_sym
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @args = args
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @switch = nil
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def switch=(switch)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @switch = switch
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
    
        data/spec.template.yml
    ADDED
    
    | 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            nodes:
         
     | 
| 
      
 2 
     | 
    
         
            +
              - name: C0
         
     | 
| 
      
 3 
     | 
    
         
            +
                type: docker # optional (default: docker)
         
     | 
| 
      
 4 
     | 
    
         
            +
                image: slankdev/ubuntu:18.04
         
     | 
| 
      
 5 
     | 
    
         
            +
                interfaces:
         
     | 
| 
      
 6 
     | 
    
         
            +
                  - { name: net0, type: direct, args: C1#net0 }
         
     | 
| 
      
 7 
     | 
    
         
            +
                  - { name: net1, type: bridge, args: B0 }
         
     | 
| 
      
 8 
     | 
    
         
            +
                  - { name: net2, type: veth  , args: peer0 }
         
     | 
| 
      
 9 
     | 
    
         
            +
                  - { name: net3, type: phys }
         
     | 
| 
      
 10 
     | 
    
         
            +
                cmds:
         
     | 
| 
      
 11 
     | 
    
         
            +
                  - cmd: ip link set dev net0 up
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              - name: C1
         
     | 
| 
      
 14 
     | 
    
         
            +
                type: netns # optional (default: docker)
         
     | 
| 
      
 15 
     | 
    
         
            +
                interfaces:
         
     | 
| 
      
 16 
     | 
    
         
            +
                  - { name: net0, type: direct, args: C0#net0 }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  - { name: net1, type: bridge, args: B0 }
         
     | 
| 
      
 18 
     | 
    
         
            +
                cmds:
         
     | 
| 
      
 19 
     | 
    
         
            +
                  - cmd: echo slankdev slankdev
         
     | 
| 
      
 20 
     | 
    
         
            +
                  - cmd: >-
         
     | 
| 
      
 21 
     | 
    
         
            +
                      echo slankdev &&
         
     | 
| 
      
 22 
     | 
    
         
            +
                      echo slnakdev
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            switches:
         
     | 
| 
      
 25 
     | 
    
         
            +
              - name: B0
         
     | 
| 
      
 26 
     | 
    
         
            +
                interfaces:
         
     | 
| 
      
 27 
     | 
    
         
            +
                  - { name: net0, type: docker, args: C0 }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  - { name: net0, type: netns, args: C1 }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            test:
         
     | 
| 
      
 31 
     | 
    
         
            +
              - name: p2p
         
     | 
| 
      
 32 
     | 
    
         
            +
                cmds:
         
     | 
| 
      
 33 
     | 
    
         
            +
                - cmd: docker exec C0 ping -c2 10.0.0.2
         
     | 
| 
      
 34 
     | 
    
         
            +
                - cmd: echo slankdev slankdev
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              - name: lo
         
     | 
| 
      
 37 
     | 
    
         
            +
                cmds:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - cmd: docker exec C0 ping -c2 10.255.0.1
         
     | 
| 
      
 39 
     | 
    
         
            +
                - cmd: echo slankdev slankdev
         
     | 
    
        data/tinet.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            lib = File.expand_path("lib", __dir__)
         
     | 
| 
      
 2 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "tinet/version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 6 
     | 
    
         
            +
              spec.name          = "tinet"
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.version       = Tinet::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.authors       = ["koki-sato"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.email         = ["admin@koki-sato.com"]
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              spec.summary       = "Ruby implement of slankdev/tinet."
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.homepage      = "https://github.com/koki-sato/tinet-rb"
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.license       = "MIT"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              spec.metadata["homepage_uri"] = spec.homepage
         
     | 
| 
      
 16 
     | 
    
         
            +
              spec.metadata["source_code_uri"] = "https://github.com/koki-sato/tinet-rb"
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.metadata["changelog_uri"] = "https://github.com/koki-sato/tinet-rb/blob/master/CHANGELOG.md"
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # Specify which files should be added to the gem when it is released.
         
     | 
| 
      
 20 
     | 
    
         
            +
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         
     | 
| 
      
 21 
     | 
    
         
            +
              spec.files         = Dir.chdir(File.expand_path('..', __FILE__)) do
         
     | 
| 
      
 22 
     | 
    
         
            +
                `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|sample|features)/}) }
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.bindir        = "bin"
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              spec.add_dependency "thor"
         
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 2.0"
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_development_dependency "rake", "~> 10.0"
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.add_development_dependency "rspec", "~> 3.0"
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,132 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: tinet
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.2
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - koki-sato
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-10-08 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: thor
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 69 
     | 
    
         
            +
            description: 
         
     | 
| 
      
 70 
     | 
    
         
            +
            email:
         
     | 
| 
      
 71 
     | 
    
         
            +
            - admin@koki-sato.com
         
     | 
| 
      
 72 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 73 
     | 
    
         
            +
            - tinet
         
     | 
| 
      
 74 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 75 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 76 
     | 
    
         
            +
            files:
         
     | 
| 
      
 77 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
      
 78 
     | 
    
         
            +
            - ".rspec"
         
     | 
| 
      
 79 
     | 
    
         
            +
            - CHANGELOG.md
         
     | 
| 
      
 80 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 81 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 82 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 83 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 84 
     | 
    
         
            +
            - bin/tinet
         
     | 
| 
      
 85 
     | 
    
         
            +
            - lib/tinet.rb
         
     | 
| 
      
 86 
     | 
    
         
            +
            - lib/tinet/cli.rb
         
     | 
| 
      
 87 
     | 
    
         
            +
            - lib/tinet/command/base.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - lib/tinet/command/build.rb
         
     | 
| 
      
 89 
     | 
    
         
            +
            - lib/tinet/command/conf.rb
         
     | 
| 
      
 90 
     | 
    
         
            +
            - lib/tinet/command/down.rb
         
     | 
| 
      
 91 
     | 
    
         
            +
            - lib/tinet/command/exec.rb
         
     | 
| 
      
 92 
     | 
    
         
            +
            - lib/tinet/command/init.rb
         
     | 
| 
      
 93 
     | 
    
         
            +
            - lib/tinet/command/ps.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - lib/tinet/command/pull.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - lib/tinet/command/up.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - lib/tinet/data.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - lib/tinet/link.rb
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib/tinet/node.rb
         
     | 
| 
      
 99 
     | 
    
         
            +
            - lib/tinet/setting.rb
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib/tinet/shell.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib/tinet/switch.rb
         
     | 
| 
      
 102 
     | 
    
         
            +
            - lib/tinet/version.rb
         
     | 
| 
      
 103 
     | 
    
         
            +
            - spec.template.yml
         
     | 
| 
      
 104 
     | 
    
         
            +
            - tinet.gemspec
         
     | 
| 
      
 105 
     | 
    
         
            +
            homepage: https://github.com/koki-sato/tinet-rb
         
     | 
| 
      
 106 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 107 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 108 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 109 
     | 
    
         
            +
              homepage_uri: https://github.com/koki-sato/tinet-rb
         
     | 
| 
      
 110 
     | 
    
         
            +
              source_code_uri: https://github.com/koki-sato/tinet-rb
         
     | 
| 
      
 111 
     | 
    
         
            +
              changelog_uri: https://github.com/koki-sato/tinet-rb/blob/master/CHANGELOG.md
         
     | 
| 
      
 112 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 113 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 114 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 115 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 116 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 117 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 118 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 119 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 120 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 121 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 122 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 123 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 124 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 125 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 126 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 127 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 128 
     | 
    
         
            +
            rubygems_version: 2.7.6
         
     | 
| 
      
 129 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 130 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 131 
     | 
    
         
            +
            summary: Ruby implement of slankdev/tinet.
         
     | 
| 
      
 132 
     | 
    
         
            +
            test_files: []
         
     |