#!/usr/bin/env ruby # # sdc # Copyright(c) 2012 ogom # MIT Licensed # $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'cli_helper' module CLI class Base < Thor class_option :debug, type: :boolean, aliases: '-d', desc: 'Debug output' class_option :raw, type: :boolean, aliases: '-r', desc: 'Raw response body' end class Key < CLI::Base desc 'ls', 'Lists all public keys we have on record for the specified account.' def ls output sdc(config(options)).keys.all, {table: :h, exclude: [:key]}.merge(options) end desc 'get [NAME]', 'Retrieves an individual key record.' def get(name) output sdc(config(options)).keys.read(name), {only: :key}.merge(options) end desc 'add [NAME] [FILE]', 'Uploads a new OpenSSH key to SmartDataCenter.' def add(name, file) raw = {name: name} raw[:key] = File.read(file) output sdc(config(options)).keys.create(raw), {table: :v, exclude: [:key]}.merge(options) end desc 'del [NAME]', 'Deletes an SSH key by name.' def del(name) output sdc(config(options)).keys.destroy(name), {message: "Key #{name} deleted"}.merge(options) end end class Datacenter < CLI::Base desc 'ls', 'Provides a list of all datacenters this cloud is aware of.' def ls output sdc(config(options)).datacenters.all, {table: :v}.merge(options) end desc 'get [NAME]', 'Gets an individual datacenter by name.' def get(name) output sdc(config(options)).datacenters.read(name), {table: :v}.merge(options) end end class Dataset < CLI::Base desc 'ls', 'Provides a list of datasets available in this datacenter.' def ls include = [:id, :name, :urn, :version, :os] output sdc(config(options)).datasets.all, {table: :h, include: include}.merge(options) end desc 'get [ID]', 'Gets an individual dataset by id.' def get(id) output sdc(config(options)).datasets.read(id), {table: :v}.merge(options) end end class Package < CLI::Base desc 'ls', 'Provides a list of packages available in this datacenter.' def ls output sdc(config(options)).packages.all, {table: :h}.merge(options) end desc 'get [NAME]', 'Gets a package by name.' def get(name) output sdc(config(options)).packages.read(name), {table: :v}.merge(options) end end class Tag < CLI::Base class_option :uuid, type: :string, aliases: '-u', desc: 'Machine uuid' desc 'ls', 'Returns the complete set of tags associated with this machine.' def ls uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.tags(uuid).all, {table: :v}.merge(opt(ARGV, options)) end desc 'get [KEY]', 'Returns the value for a single tag on this machine.' def get(key) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.tags(uuid).read(key), {'raw' => true}.merge(opt(ARGV, options)) end desc 'add [KEY] [VALUE]', 'Allows you to add additional tags, other than those set at provisioning time.' def add(key, value) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.tags(uuid).create({key => value}), {table: :v}.merge(opt(ARGV, options)) end desc 'del [KEY]', 'Deletes tag from this machine.' method_option :all, type: :boolean, desc: 'All tags delete.' def del(key=nil) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid if key.nil? if options.all msg = "Machine #{uuid} all tags deleted" output sdc(config(opt(ARGV, options))).machines.tags(uuid).destroy, {message: msg}.merge(opt(ARGV, options)) end else msg = "Machine #{uuid} tag #{key} deleted" output sdc(config(opt(ARGV, options))).machines.tags(uuid).destroy(key), {message: msg}.merge(opt(ARGV, options)) end end end class Metadata < CLI::Base class_option :uuid, type: :string, aliases: '-u', desc: 'Machine uuid' desc 'ls', 'Returns the complete set of metadata associated with this machine.' def ls uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.metadata(uuid).read, {table: :v}.merge(opt(ARGV, options)) end desc 'add [KEY] [VALUE]', 'Allows you to update the metadata for a given machine.' def add(key, value) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.metadata(uuid).create({key => value}), {table: :v}.merge(opt(ARGV, options)) end desc 'del [KEY]', 'Deletes metadata key from this machine.' method_option :all, type: :boolean, desc: 'All metadata delete.' def del(key=nil) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid if key.nil? if options.all msg = "Machine #{uuid} all metadata deleted" output sdc(config(opt(ARGV, options))).machines.metadata(uuid).destroy, {message: msg}.merge(opt(ARGV, options)) end else msg = "Machine #{uuid} metadata #{key} deleted" output sdc(config(opt(ARGV, options))).machines.metadata(uuid).destroy(key), {message: msg}.merge(opt(ARGV, options)) end end end class Snapshot < CLI::Base class_option :uuid, type: :string, aliases: '-u', desc: 'Machine uuid' desc 'ls', 'Lists all snapshots taken for a given machine.' def ls uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.snapshots(uuid).all, {table: :h}.merge(opt(ARGV, options)) end desc 'get [NAME]', 'Gets the state of the named snapshot.' def get(name) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.snapshots(uuid).read(name), {table: :v}.merge(opt(ARGV, options)) end desc 'add [NAME]', 'Allows you to take a snapshot of a machine.' def add(name) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid output sdc(config(opt(ARGV, options))).machines.snapshots(uuid).create({name: name}), {table: :v}.merge(opt(ARGV, options)) end desc 'del [NAME]', 'Deletes the specified snapshot of a machine.' def del(name) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid msg = "Machine #{uuid} snapshots #{options[:name]} deleted" output sdc(config(opt(ARGV, options))).machines.snapshots(uuid).destroy(name), {message: msg}.merge(opt(ARGV, options)) end desc 'start [NAME]', 'Starts a stopped machine from the referenced snapshot.' def start(name) uuid = options.uuid.nil? ? config[:use_machine] : options.uuid msg = "Machine #{uuid} snapshots #{options[:key]} started" output sdc(config(opt(ARGV, options))).machines.snapshots(uuid).start(name), {message: msg}.merge(opt(ARGV, options)) end end class Machine < CLI::Base desc 'ls', 'Lists all machines on record for an account.' method_option :type, type: :string, aliases: '-t', desc: 'virtualmachine or smartmachine' method_option :state, type: :string, aliases: '-s', desc: 'running or stopped' def ls include = [:id, :name, :dataset, :state] output sdc(config(options)).machines.all(options), {table: :h, include: include}.merge(options) end desc 'get [UUID]', 'Gets the details for an individual machine.' def get(uuid=nil) uuid ||= config[:use_machine] output sdc(config(options)).machines.read(uuid), {table: :v}.merge(options) end desc 'add [NAME]', 'Allows you to provision a machine.' method_option :dataset, type: :string, aliases: '-e', desc: 'dataset URN; default is indicated in ListDatasets' method_option :package, type: :string, aliases: '-p', desc: 'Name of the package to use on provisioning; default is indicated in ListPackages' def add(name) output sdc(config(options)).machines.create({name: name}.merge(options)), {table: :v}.merge(options) end desc 'del [UUID]', 'Allows you to completely destroy a machine.' def del(uuid=nil) uuid ||= config[:use_machine] output sdc(config(options)).machines.destroy(uuid), {message: "Machine #{uuid} deleted"}.merge(options) end desc 'stop [UUID]', 'Allows you to shut down a machine.' def stop(uuid=nil) uuid ||= config[:use_machine] output sdc(config(options)).machines.stop(uuid), {message: "Machine #{uuid} stoped"}.merge(options) end desc 'start [UUID]', 'Allows you to boot up a machine.' def start(uuid=nil) uuid ||= config[:use_machine] output sdc(config(options)).machines.start(uuid), {message: "Machine #{uuid} started"}.merge(options) end desc 'reboot [UUID]', 'Allows you to reboot a machine.' def reboot(uuid=nil) uuid ||= config[:use_machine] output sdc(config(options)).machines.reboot(uuid), {message: "Machine #{uuid} reboot"}.merge(options) end desc 'resize [UUID]', 'Allows you to resize a SmartMachine.' method_option :package, type: :string, aliases: '-p', desc: 'Use a package name returned from ListPackages' def resize(uuid=nil) uuid ||= config[:use_machine] output sdc(config(options)).machines.resize(uuid, {}.merge(options)), {message: "Machine #{uuid} resize"}.merge(options) end desc 'use [UUID]', 'Use machine.' def use(uuid=nil) config = Configure.read if uuid.nil? puts "use #{config[:use_machine]}" else config[:use_machine] = uuid Configure.write config end end register(Tag, 'tag', 'tag [COMMAND]', 'Machine tag') register(Metadata, 'metadata', 'metadata [COMMAND]', 'Machine metadata') register(Snapshot, 'snapshot', 'snapshot [COMMAND]', 'Machine snapshot') end class Analytic < CLI::Base desc 'desc', 'Retrieves the schema for instrumentations.' method_option :all, type: :boolean, desc: 'All describe.' method_option :output, type: :string, :default => 'metrics', aliases: '-o', desc: 'Only output the modules or fields or types or metrics or transformations.' def desc if options['raw'] puts sdc(config(options)).analytics.describe.body else content = sdc(config(options)).analytics.describe.content describe('modules', content, {cols: ['key', 'label']}.merge(options)) describe('fields', content, {cols: ['key', 'label', 'type']}.merge(options)) describe('types', content, {cols: ['key', 'name', 'arity', 'unit', 'abbr', 'base', 'power']}.merge(options)) describe('metrics', content, {cols: :all, exclude: [:fields]}.merge(options)) describe('transformations', content, {cols: ['key', 'label']}.merge(options)) end end desc 'ls', 'Retrieves all currently created instrumentations.' def ls include = ['id', 'module', 'stat', 'decomposition'] output sdc(config(options)).analytics.all, {table: :h, include: include}.merge(options) end desc 'get [ID]', 'Retrieves the configuration for an instrumentation.' method_option :value, type: :boolean, aliases: '-v', desc: 'All metadata.' def get(id) if options[:value] output sdc(config(options)).analytics.value(id), {table: :v}.merge(options) else output sdc(config(options)).analytics.read(id), {table: :v, exclude: ['uris']}.merge(options) end end desc 'add [NAME]', 'Creates an instrumentation.' method_option :module, type: :string, aliases: '-m', desc: 'The Cloud analytics module' method_option :stat, type: :string, aliases: '-s', desc: 'The Cloud analytics stat' def add output sdc(config(options)).analytics.create(options), {table: :v, exclude: ['uris']}.merge(options) end desc 'del [ID]', 'Destroys an instrumentation.' def del(id) output sdc(config(opt(ARGV, options))).analytics.destroy(id), {message: "Analytic #{id} deleted"}.merge(opt(ARGV, options)) end desc 'heatmap [ID]', 'Retrieves a particular instrumentation heatmap.' method_option :image, type: :boolean, aliases: '-i', desc: 'Heatmap image file.' method_option :x, type: :numeric, aliases: '-x', desc: 'X-Axis' method_option :y, type: :numeric, aliases: '-y', desc: 'Y-Axis' def heatmap(id) if options[:image] output sdc(config(options)).analytics.heatmap(id).image, {table: :v, exclude: ['image', 'present']}.merge(options) else client = sdc(config(options)) content = client.analytics.heatmap(id).image.content query = {'ymin' => content['ymin'], 'ymax' => content['ymax']} output client.analytics.heatmap(id).details(query.merge(options)), {table: :v}.merge(options) end end end class Main < Thor desc 'init', 'Sets up an account on a datacenter for use with this CLI.' def init Configure.make puts sdc(config).datacenters.all.status == 200 ? 'Successful configuration.' : 'Failed Configuration.' end register(Key, 'key', 'key [COMMAND]', 'SSH key') register(Datacenter, 'datacenter', 'datacenter [COMMAND]', 'Smart Data Center') register(Dataset, 'dataset', 'dataset [COMMAND]', 'Machine operating system') register(Package, 'package', 'package [COMMAND]', 'Machine resources') register(Machine, 'machine', 'machine [COMMAND]', 'Virtual machine') register(Analytic, 'analytic', 'analytic [COMMAND]', 'DTrace analytics') end end CLI::Main.start