Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

GH-690 Joyent Cloud Provider #739

Closed
wants to merge 9 commits into from

4 participants

Kevin Chan twojcik Wesley Beary Rodrigo Dellacqua
Kevin Chan
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?

Wesley Beary
Owner

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

Wesley Beary geemus referenced this pull request
Closed

Add Joyent Cloud support #690

Wesley Beary
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
Kevin Chan
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!

Wesley Beary
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.

Wesley Beary
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
Kevin Chan 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
Kevin Chan kevinykchan Fixes dataset tests 9ef1c52
Kevin Chan kevinykchan - Fixes tests to run in both mock and non-mock mode
 - Clean ups and fixes
01c92c8
Kevin Chan
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.

Wesley Beary
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?

Kevin Chan
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.

Rodrigo Dellacqua

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

Wesley Beary
Owner

Merged, thanks!

Wesley Beary geemus closed this
Rodrigo Dellacqua

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. Kevin Chan

    GH-690 Joyent Cloud Provider

    kevinykchan authored
    Squashed from fog/joyent
Commits on Feb 18, 2012
  1. Kevin Chan
Commits on Feb 20, 2012
  1. Wesley Beary
  2. Wesley Beary
  3. Wesley Beary
Commits on Feb 21, 2012
  1. Kevin Chan

    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. Kevin Chan

    Fixes dataset tests

    kevinykchan authored
  3. Kevin Chan

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

    kevinykchan authored
     - Clean ups and fixes
Commits on Feb 23, 2012
  1. Kevin Chan
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
1  lib/fog/bin.rb
View
@@ -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'
31 lib/fog/bin/joyent.rb
View
@@ -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
3  lib/fog/compute.rb
View
@@ -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)
8 lib/fog/joyent.rb
View
@@ -0,0 +1,8 @@
+module Fog
+ module Joyent
+ extend Fog::Provider
+
+ service(:compute, 'joyent/compute', 'Compute')
+
+ end
+end
194 lib/fog/joyent/compute.rb
View
@@ -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
17 lib/fog/joyent/models/compute/flavor.rb
View
@@ -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
25 lib/fog/joyent/models/compute/flavors.rb
View
@@ -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
18 lib/fog/joyent/models/compute/image.rb
View
@@ -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
25 lib/fog/joyent/models/compute/images.rb
View
@@ -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
19 lib/fog/joyent/models/compute/key.rb
View
@@ -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
34 lib/fog/joyent/models/compute/keys.rb
View
@@ -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
117 lib/fog/joyent/models/compute/server.rb
View
@@ -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
35 lib/fog/joyent/models/compute/servers.rb
View
@@ -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
45 lib/fog/joyent/models/compute/snapshot.rb
View
@@ -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
37 lib/fog/joyent/models/compute/snapshots.rb
View
@@ -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
20 lib/fog/joyent/requests/compute/add_machine_tags.rb
View
@@ -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
56 lib/fog/joyent/requests/compute/create_key.rb
View
@@ -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
16 lib/fog/joyent/requests/compute/create_machine.rb
View
@@ -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
18 lib/fog/joyent/requests/compute/create_machine_snapshot.rb
View
@@ -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
16 lib/fog/joyent/requests/compute/delete_all_machine_metadata.rb
View
@@ -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
15 lib/fog/joyent/requests/compute/delete_all_machine_tags.rb
View
@@ -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
29 lib/fog/joyent/requests/compute/delete_key.rb
View
@@ -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
15 lib/fog/joyent/requests/compute/delete_machine.rb
View
@@ -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
18 lib/fog/joyent/requests/compute/delete_machine_metadata.rb
View
@@ -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
21 lib/fog/joyent/requests/compute/delete_machine_snapshot.rb
View
@@ -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
15 lib/fog/joyent/requests/compute/delete_machine_tag.rb
View
@@ -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
28 lib/fog/joyent/requests/compute/get_dataset.rb
View
@@ -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
29 lib/fog/joyent/requests/compute/get_key.rb
View
@@ -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
29 lib/fog/joyent/requests/compute/get_machine.rb
View
@@ -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
25 lib/fog/joyent/requests/compute/get_machine_metadata.rb
View
@@ -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
14 lib/fog/joyent/requests/compute/get_machine_snapshot.rb
View
@@ -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
19 lib/fog/joyent/requests/compute/get_machine_tag.rb
View
@@ -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
33 lib/fog/joyent/requests/compute/get_package.rb
View
@@ -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
24 lib/fog/joyent/requests/compute/list_datasets.rb
View
@@ -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
25 lib/fog/joyent/requests/compute/list_keys.rb
View
@@ -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
14 lib/fog/joyent/requests/compute/list_machine_snapshots.rb
View
@@ -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
20 lib/fog/joyent/requests/compute/list_machine_tags.rb
View
@@ -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
25 lib/fog/joyent/requests/compute/list_machines.rb
View
@@ -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
36 lib/fog/joyent/requests/compute/list_packages.rb
View
@@ -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
15 lib/fog/joyent/requests/compute/reboot_machine.rb
View
@@ -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
13 lib/fog/joyent/requests/compute/resize_machine.rb
View
@@ -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
16 lib/fog/joyent/requests/compute/start_machine.rb
View
@@ -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
15 lib/fog/joyent/requests/compute/start_machine_from_snapshot.rb
View
@@ -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
16 lib/fog/joyent/requests/compute/stop_machine.rb
View
@@ -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
15 lib/fog/joyent/requests/compute/update_machine_metadata.rb
View
@@ -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
1  lib/fog/providers.rb
View
@@ -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'
3  tests/compute/helper.rb
View
@@ -20,6 +20,9 @@ def compute_providers
:glesys => {
:mocked => false
},
+ :joyent => {
+ :mocked => false
+ },
:ninefold => {
:mocked => false
},
2  tests/helper.rb
View
@@ -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)[/]")
2  tests/helpers/mock_helper.rb
View
@@ -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',
49 tests/joyent/requests/compute/datasets_tests.rb
View
@@ -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
47 tests/joyent/requests/compute/keys_tests.rb
View
@@ -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
67 tests/joyent/requests/compute/machines_tests.rb
View
@@ -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
68 tests/joyent/requests/compute/packages_tests.rb
View
@@ -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.