Coder Social home page Coder Social logo

stacker_bee's Introduction

Unofficial Ruby CloudStack client

Code Climate Dependency Status Build Status Gem Version Coverage Status

The unofficial CloudStack client for Ruby.

Installation

You can install StackerBee with rubygems:

$ gem install stacker_bee

If you are using Bundler add the following to your Gemfile:

gem 'stacker_bee'

And execute:

$ bundle install

Basic Usage

cloud_stack = StackerBee::Client.new(
  url:        'http://localhost:8080',
  api_key:    'MY_API_KEY',
  secret_key: 'MY_SECRET_KEY'
)

cloud_stack.list_virtual_machines state: 'Running'
# => [ { id: '48b91ab4...', displayName: '...', ... },
#      { id: '59c02bc5...', displayName: '...', ... },
#      ... ]

cloud_stack.create_volume name: 'MyVolume'

Features

Idomatic Ruby formatting for names

For example, you can use list_virtual_machines instead of listVirtualMachines and affinity_group_id instead of affinitygroupid (if you want to).

For example:

vm = cloud_stack.list_virtual_machines(affinity_group_id: id).first
puts vm[:iso_display_text]

Handling 'map' parameters

For any endpoint requiring a map parameter, pass in a hash.

cloud_stack.create_tags tags: { type: 'community' }, ...

This will yield a request with the following query string:

...&tags[0].key=type&tags[0].name=type&tags[0].value=community

Configurable API Version

By default, StackerBee uses the CloudStack 4.2 API, but it doesn't have to. Use a different API version by setting the api_path configuration option to the path of a JSON file containing the response from your CloudStack instance's listApis command.

StackerBee::Client.api_path = '/path/to/your/listApis/response.json'

CloudStack REPL

Usage:

$ stacker_bee [OPTIONS]

Example:

$ stacker_bee -u http://localhost:8080 -a MY_API_KEY -s MY_SECRET_KEY
StackerBee CloudStack REPL
>> list_virtual_machines state: 'Running'
=> [{"id"=>"48b91ab4-dc23-4e24-bc6f-695d58c91087",
  "name"=>"MyVM",
  "displayname"=>"My VM",
  ...
>>

Configuration

Configuring a client:

cloud_stack = StackerBee::Client.new(
  url:        'http://localhost:8080',
  api_key:    'API_KEY',
  secret_key: 'SECRET_KEY'
)

All configuration parameters set on the StackerBee::Client class are used as defaults for StackerBee::Client instances.

StackerBee::Client.url = 'http://localhost:8080'

user_client = StackerBee::Client.new(
  api_key:    'USER_API_KEY',
  secret_key: 'USER_SECRET_KEY'
)

root_client = StackerBee::Client.new(
  api_key:    'ROOT_API_KEY',
  secret_key: 'ROOT_SECRET_KEY'
)

URL

The URL of your CloudStack instance's URL.

StackerBee::Client.url = 'http://localhost:8080'

Or:

my_client = StackerBee::Client.new(
  url: 'http://localhost:8080'
)

API path

The path of your CloudStack instance's API URL. Defaults to '/client/api/'.

StackerBee::Client.api_path = '/other-path/client/api'

Or:

my_client = StackerBee::Client.new(
  api_path: '/other-path/client/api'
)

Console path

The path of your CloudStack instance's URL for console access. Defaults to '/client/console/'.

StackerBee::Client.console_path = '/other-path/client/console'

Or:

my_client = StackerBee::Client.new(
  console_path: '/other-path/client/console'
)

Keys

Your CloudStack credentials, i.e. API key and secret key.

StackerBee::Client.api_key    = 'MY_API_KEY'
StackerBee::Client.secret_key = 'MY_SECRET_KEY'

Or:

my_client = StackerBee::Client.new(
  api_key:    'MY_API_KEY',
  secret_key: 'MY_SECRET_KEY'
)

Middleware

StackerBee can be configured with middleware. It uses it's own middleware stack to implement some of its functionality.

To add a middleware, use the middlewares configuration option. For example:

class StdoutLoggingMiddleware < StackerBee::Middleware::Base
  def call(env)
    app.call(env)
    p "CloudStack call: #{env.inspect}"
  end
end

class PrependedMiddleware < StackerBee::Middleware::Base
  def call(env)
    app.call(env)
  end
end

StackerBee::Client.configuration = {
  middlewares: ->(builder) do
    # Using `before` places the middleware before the default middlewares
    builder.before PrependedMiddleware

    # Using `use` places the middleware after the default middlewares,
    # but before the request is sent to Faraday
    builder.use StdoutLoggingMiddleware
  end
}

Faraday Middleware

StackerBee is built on Faraday and allows you to add Faraday middleware. Here's an example of adding your own middleware.

StackerBee::Client.configuration = {
  faraday_middlewares: ->(faraday) do
    faraday.use Custom::LoggingMiddleware, Logger.new
    faraday.use Custom::CachingMiddleware, Rails.cache
  end
}

StackerBee itself puts some middlewares on Faraday. Any middlewares you add will be placed after these. If you want your middleware to come as the very first, you can use Faraday's builder like faraday.builder.insert 0, MyMiddleware.

Logging

You can configure logging by passing in a logger object that adheres to the standard log4* logging conventions

StackerBee::Client.configuration = {
  logger: my_log4x_logger
}

SSL and ssl_verify

StackerBee supports using SSL. To do so, use an HTTPS URL. In some deployments, CloudStack's SSL certificates don't match the DNS name that StackerBee will use to access it which will cause certificate validation errors. In these cases, if it's not feasible to fix the certificates (which is recommended) setting ssl_verfiy to false will cause StackerBee to ignore certificate validation errors.

StackerBee::Client.configuration = {
  url:        'https://my-cloudstack-server',
  ssl_verify: false # ignore certificate validation errors
}

Bulk Configuration

The StackerBee::Client class can be configured with multiple options at once.

StackerBee::Client.configuration = {
  url:        'http://localhost:8080',
  api_key:    'API_KEY',
  secret_key: 'MY_SECRET_KEY'
}

Contributing

Testing

Running the tests:

$ bundle exec rake

Testing against CloudStack

To interact with a real CloudStack server, instead of the recorded responses:

$ cp config.default.yml config.yml

And edit config.yml, specifying the URL and credentials for your CloudStack server. This file is used by the test suite if it exists, but is ignored by git.

Coding Style

This project uses Rubocop to enforce code style.

$ bundle exec rubocop

Releasing

To create a release, first bump the version in lib/stacker_bee/version.rb, and commit. Then, build the gem and release it to Rubygems with rake release:

$ rake release
stacker_bee 1.2.3 built to pkg/stacker_bee-1.2.3.gem.
Tagged v1.2.3.
Pushed git commits and tags.
Pushed stacker_bee 1.2.3 to rubygems.org.

We use Bundler's gem tasks to manage releases. See the output of rake -T and Bundler's Rubygems documentation for more information.

Thanks to

License

StackerBee is released under the MIT License.

stacker_bee's People

Contributors

nicholaides avatar gsterndale avatar justincampbell avatar dmcclory avatar ignu avatar jgarber avatar dgrizzanti avatar iamjarvo avatar jeffdeville avatar

Stargazers

 avatar Angus H. avatar Nik Wolfgramm avatar Sonny avatar 0x00evil avatar Alessandro Lepore avatar Pierre-Luc Dion avatar Jeff Moody avatar Mohit Sethi avatar  avatar  avatar  avatar  avatar Matt McManus avatar Bill Jones avatar  avatar  avatar

Watchers

 avatar  avatar  avatar Bill Jones avatar  avatar  avatar  avatar Chris Cauley avatar Jon Long avatar Gautam Naroji avatar Michael Toppa avatar James Cloos avatar Cliff Rodgers avatar Patrick Smith avatar Eric Chazan avatar Amit Thawait avatar Sarah Gray avatar  avatar  avatar  avatar Tom Li avatar Dan Corrigan avatar Carleton avatar Ryan Hinkel avatar Jay R. Newlin avatar Kara avatar Pierre-Luc Dion avatar MeghnaKale avatar Rana avatar  avatar Jesus Bracho avatar  avatar Dawn McDougall avatar Sam Vitale avatar Pat Woods avatar MK Fain avatar Avery avatar Steve Sweetney avatar Peter Nettl avatar

stacker_bee's Issues

StackerBee::Logger - progname is not always available

While trying to add a Gelf::Logger, we ran into this issue:

Gelf::Logger doesn't have a progname accessor, but StackerBee::Logger assumes that the logger class that you configure it with will have that method.

What if change it so that it only tries to set progname if the logger responds to that method?

Overridable endpoints

Applications should be able to add/modify endpoints. It's possible that CloudStack's documentation is wrong, or that users might set up proxies to CloudStack that work slightly differently that CloudStack itself.

Accept and return underscored parameter names

Right now it accepts parameters like virtual_machine_id (I think) and returns a Rash. The returned Rash can be accessed like response['virtual_machine_id'], but if you list it's keys, it will list virtualmachineid. This makes the response unable to be used for a Virtus model.

It would be cleaner to be able just accept and return data with underscored parameter names. It might also make sense to validate parameter names.

Expose API endpoints and metadata

If the API endpoints and metadata are exposed, clients of the gem can use it to do things like validate input on the browser, or before it gets sent to cloudstack.

Additionally, this information can be used by certain "fake" cloudstack servers to more realistically validate input and generate output.

different Middleware::Logging classes

Hey all,

@mattmcmanus and I tried to use StackerBee with gelf-rb's logger. We hit two problems, I'll describe the larger issue here.

when StackerBee writes to the logger, it calls multiple logger methods. It would be better to have all of the information in one GrayLog event. This is happening in StackerBee::Middleware::Logger.

We could either change the Middleware::Logger so that it only writes one method, or we could make it possible to supply your own Middleware::Logger class (in addition to your own logger)

Thoughts?

(I prefer the second approach)

README is wrong about global configuration

It says you can do this:

StackerBee::Client.url = 'http://localhost:8080/client/api'

But that doesn't work. It should be something more like this:

StackerBee::Client.configuration = { url: 'http://localhost:8080/client/api' }

Better documentation for configuration options

I feel like the documentation isn't clear about when a configuration option can be set

  • through the Client initializer
  • on the global/default configuration
  • on a Client instance via an attr_writer

Ability to add Middleware

It would be nice if users could add their own middleware. The gem itself could use this feature to add its middleware.

Cache "read" requests

Should we cache requests that do not change state? How? How do we know which requests change state?

How do we handle async requests? E.g. how do we know to expire the cache when a VM has finished being deployed?

Validation

The endpoint metadata provides type information about inputs/outputs. It also provides information about which fields are required. We can use this information to validate input before it even gets sent over the write to CloudStack.

Incorporate Rubocop into build

We already have a .rubocop file in there, but its not part of the build.

  • Running rake should run RuboCop
  • Travis should run RuboCop

Endpoint Documentation

It would be nice to have API documentation (similar to CloudStack's) that takes into account:

  • our normalized request/response key names and formats
  • the namespaces of each request (or lack thereof)

Only run Coveralls on Ruby 2.1

Not much point right now for reporting coverage for the other versions Ruby on Travis. We don't have any platform-specific code at the moment.

REPL is broken

trying to pass the api_key or secret_key from the command line (or a yaml file) doesn't work.

bundle exec stacker_bee --api_key foo --secret_key bar --url http://baz.com
/Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/configuration.rb:20:in `block in initialize': No attribute defined: 'api_key' (StackerBee::Configuration::NoAttributeError)
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/configuration.rb:18:in `each_pair'
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/configuration.rb:18:in `initialize'
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/configuration.rb:54:in `new'
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/configuration.rb:54:in `merge'
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/client.rb:101:in `configuration='
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/lib/stacker_bee/client.rb:97:in `initialize'
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/bin/stacker_bee:77:in `new'
    from /Users/dan/.gem/ruby/2.0.0/bundler/gems/stacker_bee-c9d402d83090/bin/stacker_bee:77:in `<top (required)>'
    from /Users/dan/.gem/ruby/2.0.0/bin/stacker_bee:23:in `load'
    from /Users/dan/.gem/ruby/2.0.0/bin/stacker_bee:23:in `<main>'

the configuration code isn't expecting a hash with string keys anymore

Option to turn off logging

You should be able to turn off logging by setting the logger option to nil or false. Currently, if the logger is falsy, it will be replaced with the default logger (standard out) and the only way to turn off logging is to configure it with a logger to /dev/null or something of the sort.

Rubocop

Add Rubocop to the default rake task.

https support

Hi I am getting SSL verification errors when using an https endpoint.
Is it supposed to work with https ?

Map parameters not handled correctly

The README says that a hash should be passed in for any endpoint requiring a map parameter, however these are not handled correctly.

migrateVirtualMachineWithVolume requires a map for the migrateto parameter as a volume/pool pair.

e.g. http://cloudstack/client/api?command=migrateVirtualMachineWithVolume&id=x&migrateto[0].volume=y&migrateto[0].pool=z

I'm calling stacker_bee in the following manner:
cloudstack.migrate_virtual_machine_with_volume(virtualmachineid: vm_id, hostid: host[:id], migrateto: { volume: volume[:id], pool: storage_pool[:id] })

CloudStack management server logs report that the API call that is been made is invalid:
2014-12-05 10:06:54,878 DEBUG [c.c.a.ApiServlet] (catalina-exec-12:ctx-167da945) ===START=== 10.152.100.5 -- GET apiKey=8ujy0yJMc6JHMRa2FD9N-PX6PZ7hb7rumM4cEg9szcofNZy0gj4X7Q8oCvweMQ8kok0hYjxEE9qqu7XlBx9UhA&command=migrateVirtualMachineWithVolume&hostid=8953bd6e-ff03-4143-bd98-33cef83a132d&migrateto[0].key=volume&migrateto[0].name=volume&migrateto[0].value=42326040-4a32-4436-b298-b79960cc9aa2&migrateto[1].key=pool&migrateto[1].name=pool&migrateto[1].value=4884d20b-9d45-30c8-9b30-d258b7f5fad8&response=json&virtualmachineid=510ebbe9-ea57-4f58-b519-fc033f05aaeb&signature=fy3BIeZw9FwX53xo543lsINRiOs%3D 2014-12-05 10:06:54,924 DEBUG [o.a.c.f.j.i.AsyncJobManagerImpl] (catalina-exec-12:ctx-167da945 ctx-8840e559 ctx-1109cc64) submit async job-43800, details: AsyncJobVO {id:43800, userId: 91, accountId: 2, instanceType: None, instanceId: null, cmd: org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd, cmdInfo: {"virtualmachineid":"510ebbe9-ea57-4f58-b519-fc033f05aaeb","cmdEventType":"VM.MIGRATE","ctxUserId":"91","httpmethod":"GET","migrateto[1].key":"pool","apiKey":"8ujy0yJMc6JHMRa2FD9N-PX6PZ7hb7rumM4cEg9szcofNZy0gj4X7Q8oCvweMQ8kok0hYjxEE9qqu7XlBx9UhA","response":"json","hostid":"8953bd6e-ff03-4143-bd98-33cef83a132d","migrateto[0].key":"volume","migrateto[0].name":"volume","migrateto[1].value":"4884d20b-9d45-30c8-9b30-d258b7f5fad8","ctxAccountId":"2","migrateto[1].name":"pool","ctxStartEventId":"18155","migrateto[0].value":"42326040-4a32-4436-b298-b79960cc9aa2","signature":"fy3BIeZw9FwX53xo543lsINRiOs\u003d"}, cmdVersion: 0, status: IN_PROGRESS, processStatus: 0, resultCode: 0, result: null, initMsid: 345050144322, completeMsid: null, lastUpdated: null, lastPolled: null, created: null} 2014-12-05 10:06:54,993 ERROR [c.c.a.ApiAsyncJobDispatcher] (API-Job-Executor-26:ctx-6436d07a job-43800) Unexpected exception while executing org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.