Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

GH-690 Joyent Cloud Provider #739

Closed
wants to merge 9 commits into from

4 participants

@kevinykchan
Collaborator

This implements GH-690 Joyent CloudAPI provider support

API Documentation: https://us-west-1.api.joyentcloud.com/docs

Methods implemented (everything in the docs except those under Analytics and Datacenters)

add_machine_tags
create_key
create_machine
create_machine_snapshot
delete_all_machine_metadata
delete_all_machine_tags
delete_key
delete_machine
delete_machine_metadata
delete_machine_snapshot
delete_machine_tag
get_dataset
get_key
get_machine
get_machine_metadata
get_machine_snapshot
get_machine_tag
get_package
list_datasets
list_keys
list_machine_snapshots
list_machine_tags
list_machines
list_packages
reboot_machine
resize_machine
start_machine
start_machine_from_snapshot
stop_machine
update_machine_metadata

Models provided (and their corresponding vocabulary in CloudAPI terms):

Flavor # Machine
Image # Dataset
Key # Key
Server # Machine
Snapshot # Snapshot
@twojcik

+1
Any chance it will be merged soon?

@geemus
Owner

Awesome, I'm hoping to find time to review/merge sometime this week.

@geemus geemus referenced this pull request
Closed

Add Joyent Cloud support #690

@geemus
Owner

@kevinykchan Looks great, a few questions though:

  • Why are all the credentials called :cloudapi_foo, seems like :joyent_foo might be clearer?
  • Where can I sign up for an account to test with? I tried to look at the joyent sight but wasn't sure which thing I really wanted.
  • Are you up for joining the core team to help maintain this moving forward? Thanks! wes
@kevinykchan
Collaborator

@geemus

To sign up for a Joyent account: https://my.joyentcloud.com

The credentials are prefixed with cloudapi because this provider is 100% compatible with deployments of our SmartDataCebter product in which cloudapi is a component of. But you are right, prefixing it with joyent would be more consistent. I'll fix it asap.

And sure, I'll join the team to maintain this going forward.

Thanks!

@geemus
Owner

@kevinykchan Thanks for the info. I can see why cloudapi would also make sense, but I think joyent is probably the better prefix consistency-wise, so thanks for cleaning that up. Will work on getting this merged now.

@geemus
Owner

@kevinykchan I did a little cleanup, but I'm having trouble with the tests. Seems that they aren't really setup to work in non-mock mode (and when I started fixing them up to work in real they started breaking in mock). You can see my initial changes here:
https://github.com/fog/fog/tree/joyent
My expectation is that the following two things should run without failures bundle exec shindo tests/joyent and FOG_MOCK=true bundle exec shindo tests/joyent. So if you could run through those and double check and cleanup the errors that would be awesome. Just let me know if anything is unclear or I can help out. Thanks!

kevinykchan added some commits
@kevinykchan kevinykchan Revert "[joyent|compute] make password required"
This reverts commit 6e93321.

The reason for reverting this is Joyent's CloudAPI allows authenticating using
either a username/password credential pair OR using a username and SSH private key.

In http-signature authentication scheme, no password is used.
a295c9c
@kevinykchan kevinykchan Fixes dataset tests 9ef1c52
@kevinykchan kevinykchan - Fixes tests to run in both mock and non-mock mode
 - Clean ups and fixes
01c92c8
@kevinykchan
Collaborator

@geemus

I've push the fixes to the issues above to https://github.com/kevinykchan/fog/tree/joyent
I did revert your change to require cloudapi_password because both cloudapi_keyfile and cloudapi_password can be used to authenticate against our API

Test output:

$ bundle exec shindo tests/joyent
Skipping tests for dynect due to lacking credentials (add some to '~/.fog' to run them)
Skipping tests for ecloud due to lacking credentials (add some to '~/.fog' to run them)
Skipping tests for glesys due to lacking credentials (add some to '~/.fog' to run them)
Skipping tests for ninefold due to lacking credentials (add some to '~/.fog' to run them)
Skipping tests for ovirt due to lacking credentials (add some to '~/.fog' to run them)
Skipping tests for stormondemand due to lacking credentials (add some to '~/.fog' to run them)

Fog::Compute[:joyent] | dataset requests (joyent)
  #list_datasets
    + has proper format

Fog::Compute::Joyent | key requests (joyent)
  #list_keys + has proper format
  #get_key + has proper format
  #delete_key
    + returns status code 204
    + when a key no longer exists

Fog::Compute[:joyent] | machine requests (joyent)
  #list_machines
    + returns an Array of machines
    + has proper format
  #get_machine
    + has proper format

Fog::Compute[:joyent] | package requests (joyent)
  #list_packages
    + has proper format
  #get_package
    + has proper format

10 succeeded in 35.821114 seconds


  ======================

$ FOG_MOCK=true bundle exec shindo tests/joyent

Fog::Compute[:joyent] | dataset requests (joyent)
  #list_datasets
    + has proper format

Fog::Compute::Joyent | key requests (joyent)
  #list_keys + has proper format
  #get_key + has proper format
  #delete_key
    + returns status code 204
    + when a key no longer exists

Fog::Compute[:joyent] | machine requests (joyent)
  #list_machines
    + correct number of machines
    + returns an Array of machines
    + has proper format
  #get_machine
    + has proper format

Fog::Compute[:joyent] | package requests (joyent)
  #list_packages
    + has proper format
  #list_packages
    + has correct number of packages
  #get_package
    + has proper format

Please let me know if you run into more issues. I have plans to continue adding more tests in the future.

@geemus
Owner

@kevinykchan thanks for continuing to help out on this. I'm still getting one failure though, from non-mocked get_machines. Here is what I'm seeing:

geemus  ~/geemus/fog[kevinykchan]  ⌘  be shindo tests/joyent/
  Skipping tests for openstack due to lacking credentials (add some to '~/.fog' to run them)
  Skipping tests for ovirt due to lacking credentials (add some to '~/.fog' to run them)
  Skipping tests for vsphere due to lacking credentials (add some to '~/.fog' to run them)

  Fog::Compute[:joyent] | dataset requests (joyent)
    #list_datasets
      + has proper format

  Fog::Compute::Joyent | key requests (joyent)
    #list_keys + has proper format
    #get_key + has proper format
    #delete_key
      + returns status code 204
      + when a key no longer exists

  Fog::Compute[:joyent] | machine requests (joyent)
    #list_machines
      + returns an Array of machines
      + has proper format
    #get_machine
      - has proper format
      undefined method `[]' for nil:NilClass (NoMethodError)
        /Users/geemus/geemus/fog/tests/joyent/requests/compute/machines_tests.rb:60:in `block (3 levels) in <top (required)>'
        tests/helpers/formats_helper.rb:32:in `instance_eval'
        tests/helpers/formats_helper.rb:32:in `block in formats'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:139:in `instance_eval'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:139:in `assert'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:115:in `test'
        tests/helpers/formats_helper.rb:31:in `formats'
        /Users/geemus/geemus/fog/tests/joyent/requests/compute/machines_tests.rb:59:in `block (2 levels) in <top (required)>'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:79:in `instance_eval'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:79:in `tests'
        /Users/geemus/geemus/fog/tests/joyent/requests/compute/machines_tests.rb:58:in `block in <top (required)>'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:79:in `instance_eval'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:79:in `tests'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:38:in `initialize'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:14:in `new'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo.rb:14:in `tests'
        /Users/geemus/geemus/fog/tests/joyent/requests/compute/machines_tests.rb:1:in `<top (required)>'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo/bin.rb:61:in `load'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo/bin.rb:61:in `block (2 levels) in run_in_thread'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo/bin.rb:58:in `each'
        /Users/geemus/.rvm/gems/ruby-1.9.2-p290/gems/shindo-0.3.4/lib/shindo/bin.rb:58:in `block in run_in_thread'
      Action? [c,q,r,?]? c



  Fog::Compute[:joyent] | package requests (joyent)
    #list_packages
      + has proper format
    #get_package
      + has proper format

  1 failed, 9 succeeded in 23.617851 seconds

Any thoughts?

@kevinykchan
Collaborator

Ah it looks like its because you don't have any machines, I will adjust the test to check the length of the resultant.

@rgoytacaz

looking forward to be able to use this :)
Great job guys, +1.

@geemus
Owner

Merged, thanks!

@geemus geemus closed this
@rgoytacaz

Pro! New era has begun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 10, 2012
  1. @kevinykchan

    GH-690 Joyent Cloud Provider

    kevinykchan authored
    Squashed from fog/joyent
Commits on Feb 18, 2012
  1. @kevinykchan
Commits on Feb 20, 2012
  1. @geemus
  2. @geemus
  3. @geemus
Commits on Feb 21, 2012
  1. @kevinykchan

    Revert "[joyent|compute] make password required"

    kevinykchan authored
    This reverts commit 6e93321.
    
    The reason for reverting this is Joyent's CloudAPI allows authenticating using
    either a username/password credential pair OR using a username and SSH private key.
    
    In http-signature authentication scheme, no password is used.
  2. @kevinykchan

    Fixes dataset tests

    kevinykchan authored
  3. @kevinykchan

    - Fixes tests to run in both mock and non-mock mode

    kevinykchan authored
     - Clean ups and fixes
Commits on Feb 23, 2012
  1. @kevinykchan
This page is out of date. Refresh to see the latest.
Showing with 1,497 additions and 1 deletion.
  1. +1 −0  lib/fog/bin.rb
  2. +31 −0 lib/fog/bin/joyent.rb
  3. +3 −0  lib/fog/compute.rb
  4. +8 −0 lib/fog/joyent.rb
  5. +194 −0 lib/fog/joyent/compute.rb
  6. +17 −0 lib/fog/joyent/models/compute/flavor.rb
  7. +25 −0 lib/fog/joyent/models/compute/flavors.rb
  8. +18 −0 lib/fog/joyent/models/compute/image.rb
  9. +25 −0 lib/fog/joyent/models/compute/images.rb
  10. +19 −0 lib/fog/joyent/models/compute/key.rb
  11. +34 −0 lib/fog/joyent/models/compute/keys.rb
  12. +117 −0 lib/fog/joyent/models/compute/server.rb
  13. +35 −0 lib/fog/joyent/models/compute/servers.rb
  14. +45 −0 lib/fog/joyent/models/compute/snapshot.rb
  15. +37 −0 lib/fog/joyent/models/compute/snapshots.rb
  16. +20 −0 lib/fog/joyent/requests/compute/add_machine_tags.rb
  17. +56 −0 lib/fog/joyent/requests/compute/create_key.rb
  18. +16 −0 lib/fog/joyent/requests/compute/create_machine.rb
  19. +18 −0 lib/fog/joyent/requests/compute/create_machine_snapshot.rb
  20. +16 −0 lib/fog/joyent/requests/compute/delete_all_machine_metadata.rb
  21. +15 −0 lib/fog/joyent/requests/compute/delete_all_machine_tags.rb
  22. +29 −0 lib/fog/joyent/requests/compute/delete_key.rb
  23. +15 −0 lib/fog/joyent/requests/compute/delete_machine.rb
  24. +18 −0 lib/fog/joyent/requests/compute/delete_machine_metadata.rb
  25. +21 −0 lib/fog/joyent/requests/compute/delete_machine_snapshot.rb
  26. +15 −0 lib/fog/joyent/requests/compute/delete_machine_tag.rb
  27. +28 −0 lib/fog/joyent/requests/compute/get_dataset.rb
  28. +29 −0 lib/fog/joyent/requests/compute/get_key.rb
  29. +29 −0 lib/fog/joyent/requests/compute/get_machine.rb
  30. +25 −0 lib/fog/joyent/requests/compute/get_machine_metadata.rb
  31. +14 −0 lib/fog/joyent/requests/compute/get_machine_snapshot.rb
  32. +19 −0 lib/fog/joyent/requests/compute/get_machine_tag.rb
  33. +33 −0 lib/fog/joyent/requests/compute/get_package.rb
  34. +24 −0 lib/fog/joyent/requests/compute/list_datasets.rb
  35. +25 −0 lib/fog/joyent/requests/compute/list_keys.rb
  36. +14 −0 lib/fog/joyent/requests/compute/list_machine_snapshots.rb
  37. +20 −0 lib/fog/joyent/requests/compute/list_machine_tags.rb
  38. +25 −0 lib/fog/joyent/requests/compute/list_machines.rb
  39. +36 −0 lib/fog/joyent/requests/compute/list_packages.rb
  40. +15 −0 lib/fog/joyent/requests/compute/reboot_machine.rb
  41. +13 −0 lib/fog/joyent/requests/compute/resize_machine.rb
  42. +16 −0 lib/fog/joyent/requests/compute/start_machine.rb
  43. +15 −0 lib/fog/joyent/requests/compute/start_machine_from_snapshot.rb
  44. +16 −0 lib/fog/joyent/requests/compute/stop_machine.rb
  45. +15 −0 lib/fog/joyent/requests/compute/update_machine_metadata.rb
  46. +1 −0  lib/fog/providers.rb
  47. +3 −0  tests/compute/helper.rb
  48. +1 −1  tests/helper.rb
  49. +2 −0  tests/helpers/mock_helper.rb
  50. +49 −0 tests/joyent/requests/compute/datasets_tests.rb
  51. +47 −0 tests/joyent/requests/compute/keys_tests.rb
  52. +67 −0 tests/joyent/requests/compute/machines_tests.rb
  53. +68 −0 tests/joyent/requests/compute/packages_tests.rb
View
1  lib/fog/bin.rb
@@ -64,6 +64,7 @@ def collections
require 'fog/bin/glesys'
require 'fog/bin/go_grid'
require 'fog/bin/google'
+require 'fog/bin/joyent'
require 'fog/bin/libvirt'
require 'fog/bin/linode'
require 'fog/bin/local'
View
31 lib/fog/bin/joyent.rb
@@ -0,0 +1,31 @@
+class Joyent < Fog::Bin
+ class << self
+
+ def class_for(key)
+ case key
+ when :compute
+ Fog::Compute::Joyent
+ else
+ raise ArgumentError, "Unrecognized service: #{key}"
+ end
+ end
+
+ def [](service)
+ @@connections ||= Hash.new do |hash, key|
+ hash[key] = case key
+ when :compute
+ Fog::Logger.warning("Joyent[:compute] is not recommended, use Compute[:joyent] for portability")
+ Fog::Compute.new(:provider => 'Joyent')
+ else
+ raise ArgumentError, "Unrecognized service: #{key.inspect}"
+ end
+ end
+ @@connections[service]
+ end
+
+ def services
+ Fog::Joyent.services
+ end
+
+ end
+end
View
3  lib/fog/compute.rb
@@ -32,6 +32,9 @@ def self.new(attributes)
when :gogrid
require 'fog/go_grid/compute'
Fog::Compute::GoGrid.new(attributes)
+ when :joyent
+ require 'fog/joyent/compute'
+ Fog::Compute::Joyent.new(attributes)
when :libvirt
require 'fog/libvirt/compute'
Fog::Compute::Libvirt.new(attributes)
View
8 lib/fog/joyent.rb
@@ -0,0 +1,8 @@
+module Fog
+ module Joyent
+ extend Fog::Provider
+
+ service(:compute, 'joyent/compute', 'Compute')
+
+ end
+end
View
194 lib/fog/joyent/compute.rb
@@ -0,0 +1,194 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'brightbox'))
+require 'fog/compute'
+require 'multi_json'
+
+module Fog
+ module Compute
+ class Joyent < Fog::Service
+ requires :joyent_username
+
+ recognizes :joyent_password
+ recognizes :joyent_url
+ recognizes :joyent_keyname
+ recognizes :joyent_keyfile
+
+ model_path 'fog/joyent/models/compute'
+ request_path 'fog/joyent/requests/compute'
+
+ # request :list_datacenters
+ # request :get_datacenter
+
+ # Keys
+ collection :keys
+ model :key
+
+ request :list_keys
+ request :get_key
+ request :create_key
+ request :delete_key
+
+ # Images
+ collection :images
+ model :image
+ request :list_datasets
+ request :get_dataset
+
+ # Flavors
+ collection :flavors
+ model :flavor
+ request :list_packages
+ request :get_package
+
+ # Servers
+ collection :servers
+ model :server
+ request :list_machines
+ request :get_machine
+ request :create_machine
+ request :start_machine
+ request :stop_machine
+ request :reboot_machine
+ request :resize_machine
+ request :delete_machine
+
+ # Snapshots
+ collection :snapshots
+ model :snapshot
+ request :create_machine_snapshot
+ request :start_machine_from_snapshot
+ request :list_machine_snapshots
+ request :get_machine_snapshot
+ request :delete_machine_snapshot
+ request :update_machine_metadata
+ request :get_machine_metadata
+ request :delete_machine_metadata
+ request :delete_all_machine_metadata
+
+ # MachineTags
+ request :add_machine_tags
+ request :list_machine_tags
+ request :get_machine_tag
+ request :delete_machine_tag
+ request :delete_all_machine_tags
+
+ class Mock
+ def self.data
+ @data ||= Hash.new do |hash, key|
+ hash[key] = {}
+ end
+ end
+
+ def data
+ self.class.data
+ end
+
+ def initialize(options = {})
+ @joyent_username = options[:joyent_username] || Fog.credentials[:joyent_username]
+ @joyent_password = options[:joyent_password] || Fog.credentials[:joyent_password]
+ end
+
+ def request(opts)
+ raise "Not Implemented"
+ end
+ end # Mock
+
+ class Real
+ def initialize(options = {})
+ @connection_options = options[:connection_options] || {}
+ @persistent = options[:persistent] || false
+
+ @joyent_url = options[:joyent_url] || 'https://us-sw-1.api.joyentcloud.com'
+ @joyent_version = options[:joyent_version] || '~6.5'
+
+ @joyent_username = options[:joyent_username]
+
+ unless @joyent_username
+ raise ArgumentError, "options[:joyent_username] required"
+ end
+
+ if options[:joyent_keyname] && options[:joyent_keyfile]
+ if File.exists?(options[:joyent_keyfile])
+ @joyent_keyname = options[:joyent_keyname]
+ @joyent_key = File.read(options[:joyent_keyfile])
+
+ @rsa = OpenSSL::PKey::RSA.new(@joyent_key)
+
+ @header_method = method(:header_for_signature)
+ else
+ raise ArgumentError, "options[:joyent_keyfile] provided does not exist."
+ end
+ elsif options[:joyent_password]
+ @joyent_password = options[:joyent_password]
+
+ @header_method = method(:header_for_basic)
+ else
+ raise ArgumentError, "Must provide either a joyent_password or joyent_keyname and joyent_keyfile pair"
+ end
+
+ @connection = Fog::Connection.new(
+ @joyent_url,
+ @persistent,
+ @connection_options
+ )
+ end
+
+ def request(request_options = {})
+ (request_options[:headers] ||= {}).merge!({
+ "X-Api-Version" => @joyent_version,
+ "Content-Type" => "application/json",
+ "Accept" => "application/json"
+ }).merge!(@header_method.call)
+
+ if request_options[:body]
+ request_options[:body] = MultiJson.encode(request_options[:body])
+ end
+
+ response = @connection.request(request_options)
+
+ if response.headers["Content-Type"] == "application/json"
+ response.body = MultiJson.decode(response.body)
+ response.body = decode_time_props(response.body)
+ end
+
+ response
+ end
+
+ private
+
+ def header_for_basic
+ {
+ "Authorization" => "Basic #{Base64.encode64("#{@joyent_username}:#{@joyent_password}").delete("\r\n")}"
+ }
+ end
+
+ def header_for_signature
+ date = Time.now.utc.httpdate
+ signature = Base64.encode64(@rsa.sign("sha256", date)).delete("\r\n")
+ key_id = "/#{@joyent_username}/keys/#{@joyent_keyname}"
+
+ {
+ "Date" => date,
+ "Authorization" => "Signature keyId=\"#{key_id}\",algorithm=\"rsa-sha256\" #{signature}"
+ }
+ end
+
+ def decode_time_props(obj)
+ if obj.kind_of?(Hash)
+ if obj["created"]
+ obj["created"] = Time.parse(obj["created"])
+ end
+
+ if obj["updated"]
+ obj["updated"] = Time.parse(obj["updated"])
+ end
+ elsif obj.kind_of?(Array)
+ obj.map do |o|
+ decode_time_props(o)
+ end
+ end
+ obj
+ end
+ end # Real
+ end
+ end
+end
View
17 lib/fog/joyent/models/compute/flavor.rb
@@ -0,0 +1,17 @@
+module Fog
+ module Compute
+ class Joyent
+ class Flavor < Fog::Model
+
+ identity :name
+
+ attribute :name
+ attribute :memory
+ attribute :swap
+ attribute :disk
+ attribute :default
+
+ end
+ end
+ end
+end
View
25 lib/fog/joyent/models/compute/flavors.rb
@@ -0,0 +1,25 @@
+require 'fog/core/collection'
+require 'fog/joyent/models/compute/flavor'
+
+module Fog
+ module Compute
+
+ class Joyent
+ class Flavors < Fog::Collection
+
+ model Fog::Compute::Joyent::Flavor
+
+ def all
+ load(connection.list_packages().body)
+ end
+
+ def get(id)
+ data = connection.get_package(id).body
+ new(data)
+ end
+
+ end
+ end # Joyent
+
+ end # Compute
+end # Fog
View
18 lib/fog/joyent/models/compute/image.rb
@@ -0,0 +1,18 @@
+module Fog
+ module Compute
+ class Joyent
+ class Image < Fog::Model
+
+ identity :id
+
+ attribute :name
+ attribute :os
+ attribute :type
+ attribute :version
+ attribute :created, :type => :time
+ attribute :default
+
+ end
+ end
+ end
+end
View
25 lib/fog/joyent/models/compute/images.rb
@@ -0,0 +1,25 @@
+require 'fog/core/collection'
+require 'fog/joyent/models/compute/image'
+
+module Fog
+ module Compute
+
+ class Joyent
+ class Images < Fog::Collection
+
+ model Fog::Compute::Joyent::Image
+
+ def all
+ load(connection.list_datasets().body)
+ end
+
+ def get(id)
+ data = connection.get_dataset(id).body
+ new(data)
+ end
+
+ end # Images
+ end # Joyent
+
+ end # Compute
+end # Fog
View
19 lib/fog/joyent/models/compute/key.rb
@@ -0,0 +1,19 @@
+module Fog
+ module Compute
+ class Joyent
+ class Key < Fog::Model
+ identity :name
+
+ attribute :name
+ attribute :key
+
+ attribute :created, :type => :time
+
+ def destroy
+ requires :name
+ self.connection.delete_key(name)
+ end
+ end
+ end
+ end
+end
View
34 lib/fog/joyent/models/compute/keys.rb
@@ -0,0 +1,34 @@
+require 'fog/joyent/models/compute/key'
+
+module Fog
+ module Compute
+ class Joyent
+ class Keys < Fog::Collection
+
+ model Fog::Compute::Joyent::Key
+
+ def all
+ data = connection.list_keys.body
+ load(data)
+ end
+
+ def get(keyname)
+ data = connection.get_key(keyname).body
+ if data
+ new(data)
+ else
+ nil
+ end
+ end
+
+ def create(params = {})
+ raise ArgumentError, "Key name required" unless params.key?(:name)
+ raise ArgumentError, "Key body required" unless params.key?(:body)
+
+ self.connection.create_key(params)
+ end
+
+ end
+ end
+ end
+end
View
117 lib/fog/joyent/models/compute/server.rb
@@ -0,0 +1,117 @@
+require 'fog/compute/models/server'
+module Fog
+ module Compute
+ class Joyent
+
+ class Server < Fog::Compute::Server
+ identity :id
+
+ attribute :name
+ attribute :state
+ attribute :type
+ attribute :dataset
+ attribute :ips
+ attribute :memory
+ attribute :ips
+ attribute :disk
+ attribute :metadata
+
+ attribute :created, :type => :time
+ attribute :updated, :type => :time
+
+ def ready?
+ self.state == 'running'
+ end
+
+ def stopped?
+ requires :id
+ self.state == 'stopped'
+ end
+
+ def destroy
+ requires :id
+ self.connection.delete_machine(id)
+ true
+ end
+
+ def start
+ requires :id
+ self.connection.start_machine(id)
+ self.wait_for { ready? }
+ true
+ end
+
+ def stop
+ requires :id
+ self.connection.stop_machine(id)
+ self.wait_for { stopped? }
+ true
+ end
+
+ def resize(flavor)
+ requires :id
+ self.connection.resize(id, flavor)
+ true
+ end
+
+ def reboot
+ requires :id
+ self.connection.reboot_machine(id)
+ true
+ end
+
+ def snapshots
+ requires :id
+ self.connection.snapshots.all(id)
+ end
+
+ def update_metadata(data = {})
+ requires :id
+ self.connection.update_machine_metadata(self.id, data)
+ self.reload
+ true
+ end
+
+ def delete_metadata(keyname)
+ raise ArgumentError, "Must provide a key name to delete" if keyname.nil? || keyname.empty?
+ requires :id
+
+ self.connection.delete_machine_metadata(self.id, keyname)
+ true
+ end
+
+ def delete_all_metadata
+ requires :id
+ self.connection.delete_all_machine_metadata(self.id)
+ true
+ end
+
+ def tags
+ requires :id
+ self.connection.list_machine_tags(id).body
+ end
+
+ def add_tags(tags_hash = {})
+ requires :id
+ self.connection.add_machine_tags(self.id, tags_hash).body
+ end
+
+ def delete_tag(tagname)
+ requires :id
+
+ raise ArgumentError, "Must provide a tag name to delete" if tagname.nil? || tagname.empty?
+ self.connection.delete_machine_tag(self.id, tagname)
+ true
+ end
+
+ def delete_all_tags
+ requires :id
+
+ self.connection.delete_all_machine_tags(self.id)
+ true
+ end
+
+ end
+ end
+ end
+end
View
35 lib/fog/joyent/models/compute/servers.rb
@@ -0,0 +1,35 @@
+require 'fog/core/collection'
+require 'fog/joyent/models/compute/server'
+
+module Fog
+ module Compute
+
+ class Joyent
+ class Servers < Fog::Collection
+ model Fog::Compute::Joyent::Server
+
+ def all
+ load(self.connection.list_machines().body)
+ end
+
+ def create(params = {})
+ data = self.connection.create_machine(params).body
+ server = new(data)
+ server.wait_for { ready? }
+ server
+ end
+
+ def bootstrap
+ # XXX TOXO
+ end
+
+ def get(machine_id)
+ data = self.connection.get_machine(machine_id).body
+ new(data)
+ end
+
+ end
+ end # Joyent
+
+ end # Compute
+end # Fog
View
45 lib/fog/joyent/models/compute/snapshot.rb
@@ -0,0 +1,45 @@
+module Fog
+ module Compute
+ class Joyent
+ class Snapshot < Fog::Model
+ identity :name
+
+ attribute :name
+ attribute :state
+ attribute :machine_id
+ attribute :created, :type => :time
+ attribute :updated, :type => :time
+
+ def reload
+ requires :name
+ requires :machine_id
+
+ self.connection.snapshots.get(self.machine_id, self.name)
+ end
+
+ def start
+ requires :name
+ requires :machine_id
+
+ self.connection.start_machine_from_snapshot(self.machine_id, self.name)
+ true
+ end
+
+ def destroy
+ requires :name
+ requires :machine_id
+
+ self.connection.delete_machine_snapshot(self.machine_id, self.name)
+ true
+ end
+
+ def machine
+ requires :machine_id
+
+ self.connection.servers.get(self.machine_id)
+ end
+
+ end
+ end
+ end
+end
View
37 lib/fog/joyent/models/compute/snapshots.rb
@@ -0,0 +1,37 @@
+require 'fog/joyent/models/compute/snapshot'
+
+module Fog
+ module Compute
+ class Joyent
+ class Snapshots < Fog::Collection
+
+ model Fog::Compute::Joyent::Snapshot
+
+ def create(machine_id, snapshot_name)
+ data = self.connection.create_machine_snapshot(machine_id, snapshot_name).body
+ data['machine_id'] = machine_id
+ new(data)
+ end
+
+ def all(machine_id)
+ data = self.connection.list_machine_snapshots(machine_id).body.map do |m|
+ m["machine_id"] = machine_id
+ m
+ end
+ load(data)
+ end
+
+ def get(machine_id, snapshot_name)
+ data = self.connection.get_machine_snapshot(machine_id, snapshot_name).body
+ if data
+ data["machine_id"] = machine_id
+ new(data)
+ else
+ nil
+ end
+ end
+
+ end
+ end
+ end
+end
View
20 lib/fog/joyent/requests/compute/add_machine_tags.rb
@@ -0,0 +1,20 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Real
+ # https://us-west-1.api.joyentcloud.com/docs#AddMachineTags
+ def add_machine_tags(machine_id, tags={})
+ raise ArgumentError, "tags must be a Hash of tags" unless tags.is_a?(Hash)
+
+ request(
+ :path => "/my/machines/#{machine_id}/tags",
+ :method => "POST",
+ :body => tags,
+ :expects => 200
+ )
+ end
+ end
+ end
+ end
+end
View
56 lib/fog/joyent/requests/compute/create_key.rb
@@ -0,0 +1,56 @@
+module Fog
+ module Compute
+ class Joyent
+ class Mock
+ #
+ # https://us-west-1.api.joyentcloud.com/docs#CreateKey
+ #
+ def create_key(params)
+ name = params[:name]
+ key = params[:key]
+
+ record = {
+ "name" => name,
+ "key" => key,
+ "created" => Time.now.utc,
+ "updated" => Time.now.utc
+ }
+
+ self.data[:keys][name] = record
+
+ response = Excon::Response.new
+ response.status = 201
+ response.body = record
+ response
+ end
+ end # Mock
+
+ class Real
+
+ # Creates a new SSH Key
+ # ==== Parameters
+ # * name<~String> - Name to assign to this key
+ # * key<~String> - OpenSSH formatted public key
+ #
+ # ==== Returns
+ # * response<~Excon::Response>:
+ # * body<~Hash>:
+ # * 'name'<~String> - Name for this key
+ # * 'key'<~String> - OpenSSH formatted public key
+ #
+ def create_key(params={})
+ raise ArgumentError, "error creating key: [name] is required" unless params[:name]
+ raise ArgumentError, "error creating key: [key] is required" unless params[:key]
+
+ request(
+ :method => "POST",
+ :path => "/my/keys",
+ :body => { "name" => params[:name], "key" => params[:key] },
+ :expects => 201
+ )
+ end
+
+ end
+ end
+ end
+end
View
16 lib/fog/joyent/requests/compute/create_machine.rb
@@ -0,0 +1,16 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def create_machine(params = {})
+ request(
+ :method => "POST",
+ :path => "/my/machines",
+ :body => params,
+ :expects => [200, 201, 202]
+ )
+ end
+ end
+ end
+ end
+end
View
18 lib/fog/joyent/requests/compute/create_machine_snapshot.rb
@@ -0,0 +1,18 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+
+ def create_machine_snapshot(machine_id, snapshot_name)
+ request(
+ :method => "POST",
+ :path => "/my/machines/#{machine_id}/snapshots",
+ :body => {"name" => snapshot_name },
+ :expects => [201]
+ )
+ end
+
+ end
+ end
+ end
+end
View
16 lib/fog/joyent/requests/compute/delete_all_machine_metadata.rb
@@ -0,0 +1,16 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ # https://us-west-1.api.joyentcloud.com/docs#DeleteMachineMetadata
+ def delete_all_machine_metadata(machine_id)
+ request(
+ :method => "DELETE",
+ :path => "/my/machines/#{machine_id}/metadata",
+ :expects => 204
+ )
+ end
+ end
+ end
+ end
+end
View
15 lib/fog/joyent/requests/compute/delete_all_machine_tags.rb
@@ -0,0 +1,15 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def delete_all_machine_tags(machine_id)
+ request(
+ :path => "/my/machines/#{machine_id}/tags",
+ :method => "DELETE",
+ :expects => 204
+ )
+ end
+ end
+ end
+ end
+end
View
29 lib/fog/joyent/requests/compute/delete_key.rb
@@ -0,0 +1,29 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Mock
+ def delete_key(keyname)
+ if self.data[:keys].delete(keyname)
+ response = Excon::Response.new
+ response.status = 204
+ response
+ else
+ raise Excon::Errors::NotFound, "Not Found"
+ end
+ end
+ end
+
+ class Real
+ def delete_key(name)
+ request(
+ :method => "DELETE",
+ :path => "/my/keys/#{name}",
+ :expects => 204
+ )
+ end
+ end # Real
+
+ end
+ end
+end
View
15 lib/fog/joyent/requests/compute/delete_machine.rb
@@ -0,0 +1,15 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def delete_machine(machine_id)
+ request(
+ :path => "/my/machines/#{machine_id}",
+ :method => "DELETE",
+ :expects => [200, 204]
+ )
+ end
+ end
+ end
+ end
+end
View
18 lib/fog/joyent/requests/compute/delete_machine_metadata.rb
@@ -0,0 +1,18 @@
+module Fog
+ module Compute
+
+ class Joyent
+ class Real
+
+ # https://us-west-1.api.joyentcloud.com/docs#DeleteAllMachineMetadata
+ def delete_machine_metadata(machine_id, key)
+ request(
+ :method => "DELETE",
+ :path => "/my/machines/#{machine_id}/metadata/#{key}",
+ :expects => [200, 204]
+ )
+ end
+ end
+ end
+ end
+end
View
21 lib/fog/joyent/requests/compute/delete_machine_snapshot.rb
@@ -0,0 +1,21 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Real
+ def delete_machine_snapshot(machine_id, snapshot)
+ request(
+ :method => "DELETE",
+ :path => "/my/machines/#{machine_id}/snapshots/#{snapshot}",
+ :expects => [200, 204]
+ )
+ end
+ end
+
+ class Mock
+
+ end
+
+ end
+ end
+end
View
15 lib/fog/joyent/requests/compute/delete_machine_tag.rb
@@ -0,0 +1,15 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def delete_machine_tag(machine_id, tagname)
+ request(
+ :path => "/my/machines/#{machine_id}/tags/#{tagname}",
+ :method => "DELETE",
+ :expects => 204
+ )
+ end
+ end
+ end
+ end
+end
View
28 lib/fog/joyent/requests/compute/get_dataset.rb
@@ -0,0 +1,28 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Mock
+ def get_dataset(id)
+ if ds = self.data[:datasets][id]
+ res = Excon::Response.new
+ res.status = 200
+ res.body = ds
+ else
+ raise Excon::Errors::NotFound
+ end
+ end
+ end
+
+ class Real
+ def get_dataset
+ request(
+ :method => "GET",
+ :path => "/my/datasets"
+ )
+ end
+ end
+
+ end
+ end
+end
View
29 lib/fog/joyent/requests/compute/get_key.rb
@@ -0,0 +1,29 @@
+module Fog
+ module Compute
+ class Joyent
+ class Mock
+
+ def get_key(keyid)
+ if key = self.data[:keys][keyid]
+ response = Excon::Response.new
+ response.status = 200
+ response.body = key
+ response
+ else
+ raise Excon::Errors::NotFound
+ end
+ end
+ end
+
+ class Real
+ def get_key(keyid)
+ request(
+ :method => "GET",
+ :path => "/my/keys/#{keyid}",
+ :expects => 200
+ )
+ end
+ end
+ end
+ end
+end
View
29 lib/fog/joyent/requests/compute/get_machine.rb
@@ -0,0 +1,29 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Mock
+ def get_machine(uuid)
+ if machine = self.data[:machines][uuid]
+ res = Excon::Response.new
+ res.status = 200
+ res.body = machine
+ res
+ else
+ raise Excon::Errors::NotFound, "Not Found"
+ end
+ end
+ end
+
+ class Real
+ def get_machine(uuid)
+ request(
+ :method => "GET",
+ :path => "/my/machines/#{uuid}",
+ :expects => 200
+ )
+ end
+ end
+ end
+ end
+end
View
25 lib/fog/joyent/requests/compute/get_machine_metadata.rb
@@ -0,0 +1,25 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+
+ def get_machine_metadata(machine_id, options = {})
+ query = {}
+ if options[:credentials]
+ if options[:credentials].is_a?(Boolean)
+ query[:credentials] = options[:credentials]
+ else
+ raise ArgumentError, "options[:credentials] must be a Boolean or nil"
+ end
+ end
+
+ request(
+ :path => "/my/machines/#{machine_id}/metadata",
+ :query => query
+ )
+ end
+
+ end
+ end
+ end
+end
View
14 lib/fog/joyent/requests/compute/get_machine_snapshot.rb
@@ -0,0 +1,14 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def get_machine_snapshot(machine_id, snapshot_name)
+ request(
+ :path => "/my/machines/#{machine_id}/snapshots/#{snapshot_name}",
+ :method => "GET"
+ )
+ end
+ end
+ end
+ end
+end
View
19 lib/fog/joyent/requests/compute/get_machine_tag.rb
@@ -0,0 +1,19 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+
+ # https://us-west-1.api.joyentcloud.com/docs#GetMachineTag
+ def get_machine_tag(machine_id, tagname)
+ request(
+ :path => "/my/machines/#{machine_id}/tags/#{tagname}",
+ :method => "GET",
+ :headers => {"Accept" => "text/plain"},
+ :expects => 200
+ )
+ end
+
+ end
+ end
+ end
+end
View
33 lib/fog/joyent/requests/compute/get_package.rb
@@ -0,0 +1,33 @@
+require 'uri'
+
+module Fog
+ module Compute
+ class Joyent
+ class Mock
+
+ def get_package(name)
+ if pkg = self.data[:packages][name]
+ response = Excon::Response.new
+ response.body = pkg
+ response.status = 200
+ response
+ else
+ raise Excon::Errors::NotFound
+ end
+ end
+ end
+
+ class Real
+ def get_package(name)
+ name = URI.escape(name)
+ request(
+ :method => "GET",
+ :path => "/my/packages/#{name}",
+ :expects => 200
+ )
+ end
+
+ end
+ end
+ end
+end
View
24 lib/fog/joyent/requests/compute/list_datasets.rb
@@ -0,0 +1,24 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Mock
+ def list_datasets
+ res = Excon::Response.new
+ res.status = 200
+ res.body = self.data[:datasets].values
+ res
+ end
+ end
+
+ class Real
+ def list_datasets
+ request(
+ :method => "GET",
+ :path => "/my/datasets"
+ )
+ end
+ end
+ end
+ end
+end
View
25 lib/fog/joyent/requests/compute/list_keys.rb
@@ -0,0 +1,25 @@
+module Fog
+ module Compute
+ class Joyent
+ class Mock
+ def list_keys
+ response = Excon::Response.new
+ response.status = 200
+ response.body = self.data[:keys].values
+ response
+ end
+ end
+
+ class Real
+ def list_keys
+ request(
+ :expects => 200,
+ :method => :'GET',
+ :path => '/my/keys'
+ )
+ end
+ end # Real
+
+ end
+ end
+end
View
14 lib/fog/joyent/requests/compute/list_machine_snapshots.rb
@@ -0,0 +1,14 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def list_machine_snapshots(machine_id)
+ request(
+ :method => "GET",
+ :path => "/my/machines/#{machine_id}/snapshots"
+ )
+ end
+ end
+ end
+ end
+end
View
20 lib/fog/joyent/requests/compute/list_machine_tags.rb
@@ -0,0 +1,20 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ # https://us-west-1.api.joyentcloud.com/docs#ListMachineTags
+ def list_machine_tags(machine_id)
+ request(
+ :path => "/my/machines/#{machine_id}/tags",
+ :method => "GET",
+ :expects => 200
+ )
+ end
+ end
+
+ class Mock
+
+ end
+ end
+ end
+end
View
25 lib/fog/joyent/requests/compute/list_machines.rb
@@ -0,0 +1,25 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Mock
+ def list_machines(options={})
+ res = Excon::Response.new
+ res.status = 200
+ res.body = self.data[:machines].values
+ res
+ end
+ end
+
+ class Real
+ def list_machines(options={})
+ request(
+ :path => "/my/machines",
+ :method => "GET",
+ :query => options
+ )
+ end
+ end
+ end
+ end
+end
View
36 lib/fog/joyent/requests/compute/list_packages.rb
@@ -0,0 +1,36 @@
+module Fog
+ module Compute
+ class Joyent
+
+ class Mock
+ def list_packages
+ response = Excon::Response.new()
+ response.status = 200
+ response.body = self.data[:packages].values
+ response
+ end
+ end
+
+ class Real
+ # Lists all the packages available to the authenticated user
+ # ==== Returns
+ # Exon::Response<Array>
+ # * name<~String> The "friendly name for this package
+ # * memory<~Number> How much memory will by available (in Mb)
+ # * disk<~Number> How much disk space will be available (in Gb)
+ # * swap<~Number> How much swap memory will be available (in Mb)
+ # * default<~Boolean> Whether this is the default package in this datacenter"
+ #
+ def list_packages
+ request(
+ :path => "/my/packages",
+ :method => "GET",
+ :expects => 200
+ )
+ end
+ end # Real
+
+ end
+
+ end
+end
View
15 lib/fog/joyent/requests/compute/reboot_machine.rb
@@ -0,0 +1,15 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def reboot_machine(id)
+ request(
+ :method => "POST",
+ :query => {"action" => "reboot"},
+ :path => "/my/machines/#{id}"
+ )
+ end
+ end
+ end
+ end
+end
View
13 lib/fog/joyent/requests/compute/resize_machine.rb
@@ -0,0 +1,13 @@
+module Fog
+ module Compute
+ class Joyent
+ def resize_machine(id, package)
+ request(
+ :method => "POST",
+ :path => "/my/machines/#{id}",
+ :query => {"action" => "resize", "package" => package}
+ )
+ end
+ end
+ end
+end
View
16 lib/fog/joyent/requests/compute/start_machine.rb
@@ -0,0 +1,16 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def start_machine(id)
+ request(
+ :method => "POST",
+ :path => "/my/machines/#{id}",
+ :query => {"action" => "start"},
+ :expects => 202
+ )
+ end
+ end
+ end
+ end
+end
View
15 lib/fog/joyent/requests/compute/start_machine_from_snapshot.rb
@@ -0,0 +1,15 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def start_machine_from_snapshot(machine_id, snapshot_name)
+ request(
+ :method => "POST",
+ :path => "/my/machines/#{machine_id}/snapshots/#{snapshot_name}",
+ :expects => 202
+ )
+ end
+ end
+ end
+ end
+end
View
16 lib/fog/joyent/requests/compute/stop_machine.rb
@@ -0,0 +1,16 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def stop_machine(uuid)
+ request(
+ :method => "POST",
+ :path => "/my/machines/#{uuid}",
+ :query => {"action" => "stop"},
+ :expects => 202
+ )
+ end
+ end
+ end
+ end
+end
View
15 lib/fog/joyent/requests/compute/update_machine_metadata.rb
@@ -0,0 +1,15 @@
+module Fog
+ module Compute
+ class Joyent
+ class Real
+ def update_machine_metadata(machine_id, metadata)
+ request(
+ :method => "POST",
+ :path => "/my/machines/#{machine_id}/metadata",
+ :body => metadata
+ )
+ end
+ end
+ end
+ end
+end
View
1  lib/fog/providers.rb
@@ -10,6 +10,7 @@
require 'fog/glesys'
require 'fog/go_grid'
require 'fog/google'
+require 'fog/joyent'
require 'fog/libvirt'
require 'fog/linode'
require 'fog/local'
View
3  tests/compute/helper.rb
@@ -20,6 +20,9 @@ def compute_providers
:glesys => {
:mocked => false
},
+ :joyent => {
+ :mocked => false
+ },
:ninefold => {
:mocked => false
},
View
2  tests/helper.rb
@@ -12,7 +12,7 @@ def array_differences(array_a, array_b)
end
# check to see which credentials are available and add others to the skipped tags list
-all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'dnsmadeeasy', 'dynect', 'ecloud', 'glesys', 'gogrid', 'google', 'linode', 'local', 'ninefold', 'newservers', 'openstack', 'ovirt', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'vsphere', 'zerigo']
+all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'dnsmadeeasy', 'dynect', 'ecloud', 'glesys', 'gogrid', 'google', 'joyent', 'linode', 'local', 'ninefold', 'newservers', 'openstack', 'ovirt', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'vsphere', 'zerigo']
available_providers = Fog.available_providers.map {|provider| provider.downcase}
for provider in (all_providers - available_providers)
Formatador.display_line("[yellow]Skipping tests for [bold]#{provider}[/] [yellow]due to lacking credentials (add some to '~/.fog' to run them)[/]")
View
2  tests/helpers/mock_helper.rb
@@ -30,6 +30,8 @@
:go_grid_shared_secret => 'go_grid_shared_secret',
:google_storage_access_key_id => 'google_storage_access_key_id',
:google_storage_secret_access_key => 'google_storage_secret_access_key',
+ :joyent_username => "joyentuser",
+ :joyent_password => "joyentpass",
:linode_api_key => 'linode_api_key',
:local_root => '~/.fog',
:new_servers_password => 'new_servers_password',
View
49 tests/joyent/requests/compute/datasets_tests.rb
@@ -0,0 +1,49 @@
+Shindo.tests("Fog::Compute[:joyent] | dataset requests", ["joyent"]) do
+ @dataset_format = {
+ "description" => String,
+ "requirements" => {},
+ "name" => String,
+ "version" => String,
+ "os" => String,
+ "id" => String,
+ "urn" => String,
+ "default" => Fog::Boolean,
+ "type" => String,
+ "created" => Time,
+ }
+
+ if Fog.mock?
+ Fog::Compute[:joyent].data[:datasets] = {
+ "33904834-1f01-49d3-bed3-b642e158c375" => {
+ "id" => "33904834-1f01-49d3-bed3-b642e158c375",
+ "urn" => "sdc:sdc:zeus-simple-lb-200mbps:1.1.1",
+ "name" => "zeus-simple-lb-200mbps",
+ "os" => "smartos",
+ "type" => "smartmachine",
+ "description" => "Zeus Simple Load Balancer 200 Mbps SmartMachine",
+ "default" => false,
+ "requirements" => {},
+ "version" => "1.1.1",
+ "created" => Time.parse("2011-09-15T07:39:13+00:00")
+ },
+ "3fcf35d2-dd79-11e0-bdcd-b3c7ac8aeea6" => {
+ "id" => "3fcf35d2-dd79-11e0-bdcd-b3c7ac8aeea6",
+ "urn" => "sdc:sdc:mysql:1.4.1",
+ "name" => "mysql",
+ "os" => "smartos",
+ "type" => "smartmachine",
+ "description" => "MySQL SmartMachine",
+ "default" => false,
+ "requirements" => {},
+ "version" => "1.4.1",
+ "created" => Time.parse("2011-09-15T05:01:34+00:00")
+ }
+ }
+ end
+
+ tests("#list_datasets") do
+ formats(@dataset_format) do
+ Fog::Compute[:joyent].list_datasets.body.first
+ end
+ end
+end
View
47 tests/joyent/requests/compute/keys_tests.rb
@@ -0,0 +1,47 @@
+Shindo.tests("Fog::Compute[:joyent] | key requests", ['joyent']) do
+
+ @key_format = {
+ "name" => String,
+ "key" => String,
+ "created" => Time,
+ "updated" => Time
+ }
+
+ before do
+ #
+ # Clear out all the test keys on the account in prep for test
+ #
+ Fog::Compute[:joyent].list_keys.body.each do |key|
+ if key["name"] =~ /^fog-test/
+ Fog::Compute[:joyent].delete_key(key["name"])
+ end
+ end
+
+ @test_key_name = "fog-test-#{Time.now.utc.to_i}"
+
+ Fog::Compute[:joyent].create_key(
+ :name => @test_key_name,
+ :key => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWxSNYngOTeu0pYd+2tpfYGISuMfMUNGyAIh4yRprAbacVddRq4Nyr12vDklzaRTzgd9PgX/82JMb4RARbVTtUKXJXmaBLvg2epGM+ScanZIitzL53whJrlGx+7nT+TnRdkB1XG7uIf2EpTQBaKrT4iG0magCXh5bmOqCyWte2gV8fArMg5bZclUT1p2E7qEW0htaLOiMSyGkjBlxb6vYQCA/Pa8VWETHehIF46S942gCj0aaL81gTocfyTm5/F+AgvUAsjHzRVkB/Dlhwq7Q7sK+4iAhlKPYMflkKC8r+nF0/LL9S3lllLZvbkEWJfEqlMCAbgmjTpYlBzQEqf/eN"
+ )
+ end
+
+ tests("#list_keys").formats(@key_format) do
+ Fog::Compute[:joyent].list_keys.body.first
+ end
+
+ tests("#get_key").formats(@key_format) do
+ Fog::Compute[:joyent].get_key(@test_key_name).body
+ end
+
+ tests("#delete_key") do
+ returns(204 , "returns status code 204") do
+ Fog::Compute[:joyent].delete_key(@test_key_name).status
+ end
+
+ raises(Excon::Errors::NotFound, "when a key no longer exists") do
+ Fog::Compute[:joyent].delete_key(@test_key_name)
+ Fog::Compute[:joyent].delete_key(@test_key_name)
+ end
+ end
+
+end
View
67 tests/joyent/requests/compute/machines_tests.rb
@@ -0,0 +1,67 @@
+Shindo.tests("Fog::Compute[:joyent] | machine requests", ["joyent"]) do
+
+ @machine_format = {
+ "id" => String,
+ "name" => String,
+ "type" => String,
+ "state" => String,
+ "dataset" => String,
+ "memory" => Integer,
+ "disk" => Integer,
+ "ips" => Array,
+ "metadata" => Hash,
+ "created" => Time,
+ "updated" => Time
+ }
+
+ if Fog.mock?
+ @machines = Fog::Compute[:joyent].data[:machines] = {
+ "15080eca-3786-4bb8-a4d0-f43e1981cd72" => {
+ "id" => "15080eca-3786-4bb8-a4d0-f43e1981cd72",
+ "name" => "getting-started",
+ "type" => "smartmachine",
+ "state" => "running",
+ "dataset" => "sdc:sdc:smartos:1.3.15",
+ "memory" => 256,
+ "disk" => 5120,
+ "ips" => ["10.88.88.50"],
+ "metadata" => {},
+ "created" => Time.parse("2011-06-03T00:02:31+00:00"),
+ "updated" => Time.parse("2011-06-03T00:02:31+00:00")
+ }
+ }
+ end
+
+ @provider = Fog::Compute[:joyent]
+
+
+ #
+ # https://us-west-1.api.joyentcloud.com/docs#ListMachines
+ #
+ tests("#list_machines") do
+ if Fog.mock?
+ returns(@machines.length, "correct number of machines") do
+ @provider.list_machines.body.length
+ end
+ end
+
+ returns(Array, "returns an Array of machines") do
+ @provider.list_machines.body.class
+ end
+
+ formats([@machine_format]) do
+ @provider.list_machines.body
+ end
+ end
+
+ # https://us-west-1.api.joyentcloud.com/docs#GetMachine
+ tests("#get_machine") do
+ machines = @provider.list_machines.body
+ unless machines.empty?
+ formats(@machine_format) do
+ id = machines.first["id"]
+ @provider.get_machine(id).body
+ end
+ end
+ end
+end
View
68 tests/joyent/requests/compute/packages_tests.rb
@@ -0,0 +1,68 @@
+Shindo.tests("Fog::Compute[:joyent] | package requests", ["joyent"]) do
+ @package_format = {
+ 'name' => String,
+ 'vcpus' => Integer,
+ 'memory' => Integer,
+ 'disk' => Integer,
+ 'swap' => Integer,
+ 'default' => Fog::Boolean
+ }
+
+ if Fog.mock?
+ @data = Fog::Compute[:joyent].data
+
+ @data[:packages] = {
+ "regular_128" => {
+ "name" => "regular_128",
+ "memory" => 128,
+ "disk" => 5120,
+ "vcpus" => 1,
+ "swap" => 256,
+ "default" => true
+ },
+ "regular_256" => {
+ "name" => "regular_256",
+ "memory" => 256,
+ "disk" => 5120,
+ "vcpus" => 1,
+ "swap" => 512,
+ "default" => false
+ },
+ "regular_512" => {
+ "name" => "regular_512",
+ "memory" => 512,
+ "disk" => 10240,
+ "vcpus" => 1,
+ "swap" => 1024,
+ "default" => false
+ }
+ }
+ end
+
+ tests("#list_packages") do
+ formats([@package_format]) do
+ Fog::Compute[:joyent].list_packages.body
+ end
+ end
+
+ if Fog.mock?
+ tests("#list_packages") do
+ actual = @data[:packages].values.length
+ returns(actual, "has correct number of packages") do
+ Fog::Compute[:joyent].list_packages.body.length
+ end
+ end
+ end
+
+ tests("#get_package") do
+ pkgid = if Fog.mock?
+ @data[:packages].keys.first
+ else
+ Fog::Compute[:joyent].list_packages.body.first["name"]
+ end
+
+ formats(@package_format) do
+ Fog::Compute[:joyent].get_package(pkgid).body
+ end
+ end
+end
Something went wrong with that request. Please try again.