Skip to content

Commit 96ecddb

Browse files
committed
Merge pull request #19 from softlayer/server_model
Introduces the SoftLayer object framework including Virtual Servers, Bare Metal Servers, and rudimentary Tickets.
2 parents 923006c + ab57eba commit 96ecddb

67 files changed

Lines changed: 6000 additions & 317 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
.bundle/
55
log/
66
internal_examples/
7+
doc/
8+
Gemfile.lock

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
language: ruby
22
rvm:
3+
- "2.1.2"
34
- "2.1.1"
4-
- "2.1.0"
55
- "2.0.0"
66
- "1.9.3"
77
- "1.9.2"

CHANGELOG.textile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
*2.1.0*
2+
* Began implementing a model framework that allows Ruby developers to work with elements in the SoftLayer API in a more object-oriented fashion. The first release of this framework includes the Ticket, VirtualServer, and BareMetalServer classes.
3+
14
*2.0.1*
25
* Fix broken gem configparser dependency
36

@@ -9,7 +12,7 @@ The @result_offset@ API filter has been removed.
912
* Changed the mechanism for obtaining services to include the Client class. This makes the Ruby API very similar to the API presented by the Python bindings. The old mechanism for obtaining services still works to preserve backward compatibility but you will receive deprecation warnings in debug mode.
1013

1114
*1.0.8*
12-
* Set a default User-Agent string to be sent with all requests to SoftLayer API. Provide interface to set a custom User-Agent string.
15+
* Set a default User-Agent string to be sent with all requests to SoftLayer API. Provide interface to set a custom User-Agent string.
1316

1417
*1.0.7*
1518
* Calls to the @getObject@ method of any service should not take parameters. The gem now warns if you make this type of call and ignores the parameters. This prevents @SoftLayer_Virtual_Guest::getObject@ from accidentally creating (billable) VirtualServer instances.

README.textile

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ The SoftLayer API Client for Ruby is a library for connecting to and calling the
55
<div id="note" style="margin: 1em; padding: 0.5em; background-color: #fcfcfc; border: 1px solid black">
66
*Important Note*
77

8-
Version 2.0 of the gem may require you change your existing scripts. Please see "What's New":#whats_new for details.
8+
If you are arriving at this build from verison 1.0 of the @softlayer_api@ gem, you will probably have to change some of your existing scripts. Please see "What's New":#whats-new for details.
99
</div>
1010

1111
h2. Overview
@@ -24,13 +24,23 @@ The Ruby client has been tested using a wide variety of Ruby implementations inc
2424

2525
A network connection is required, and a valid SoftLayer API username and api key are required to call the SoftLayer API. A connection to the SoftLayer private network is required to connect to SoftLayer's private network API endpoints.
2626

27-
h2(#whats_new). What's New
27+
h2(#whats-new). What's New
28+
29+
The softlayer_api gem no longer supports Ruby 1.8.x
30+
31+
**Version 2.1** of @softlayer_api@ builds an object model of SoftLayer clases on top of the low-level SoftLayer API calls. The object model provides a high-level interface to the elements within the SoftLayer environment and encapsulates some of the details of the "raw" SoftLayer API.
32+
33+
34+
With this first release, the Object Model provides classes for the SoftLayer Account, Bare Metal and Virutal servers, and Tickets. The model also provides classes to help you place orders for both Bare Metal and Virtual Servers. The class structure is not meant to be comprehensive. Our goal is to provide a simple API for performing common operations.
35+
36+
Interface documentation for the new object hierarchy is available in the gem's source. More comprehensive documentation including a design guide for new clases and a contribution guide for developers will be added in the future.
37+
38+
**Version 2.0** of the @softlayer_api@ gem changes the protocol used to communicate with the SoftLayer API from REST to XML-RPC. This change alone should not require any changes to scripts written to the version 1.0 gem. However there are two new behaviors which will require existing version 1.0 scripts to change:
2839

29-
Version 2.0 of the @softlayer_api@ gem changes the protocol used to communicate with the SoftLayer API from REST to XML-RPC. This change should not require any changes to existing scripts. However there are two new behaviors which may require you to change existing scripts:
3040
* Object Masks are now sent to the server using the "Extended Object Mask Format":http://sldn.softlayer.com/article/Object-Masks.
3141
* Result limits are now specified using a single call rather than requiring two
3242

33-
Version 2.0 does not support Ruby 1.8.x
43+
The gem now allows you to specify your SoftLayer username and API key through a config file. See "Providing authentication in a config file":#config_authorization for more information.
3444

3545
h3. XML-RPC
3646

@@ -76,7 +86,7 @@ h3. Authentication
7686

7787
That instance will have to know your "API authentication information":http://sldn.softlayer.com/article/Authenticating_to_the_SoftLayer_API consisting of your account username and API key. In addition, you will have to select an endpoint, the web address the client will use to contact the SoftLayer API. You may provide this information in a configuration file, through global variables, or by passing them to the constructor.
7888

79-
h4. Providing authentication in a config file
89+
h4(#config_authorization). Providing authentication in a config file
8090

8191
The Ruby client will look for a configuration file that can provide the username and api_key for requests. A sample configuraiton file looks like this:
8292

@@ -187,7 +197,7 @@ If you wish to limit the volume of information that the server returns about a p
187197

188198
The arguments to @object_mask@ must strings. Each string should be a well defined Object Mask as defined in the "SLDN documentation":http://sldn.softlayer.com/article/Object-Masks.
189199

190-
To look at some examples, consider the following object from the server. It has four properties: @id@, @title@, @createDate@ and @modifyDate@. It also has an entity, @assignedUser@. The @assignedUser@ entity has three properties: @id@, @username@, and @health@.
200+
To look at some examples, consider the following object from the server. It has four properties: @id@, @title@, @createDate@ and @modifyDate@. It also has an entity, @assignedUser@. The @assignedUser@ entity has three properties: @id@, @username@, and @health@.
191201

192202
<pre style="border:1pt solid black;background:#eee;padding:0.5em;margin:0.5em"><code style="font-family:Menlo,Monaco,monospace;font-size:9pt">{
193203
"id"=>1736473,
@@ -232,7 +242,7 @@ We can identify a particular set of attributes we are interested in by combining
232242
=> {"assignedUser"=>{"id"=>14, "health"=>"Fantastic"}}
233243
</code></pre>
234244

235-
Object masks are sent to the server and applied on the server side. Errors in the object mask format will lead to exceptions being thrown by the SoftLayer API. By carefully choosing an Object Mask, you can limit amount of information transferred from the server which may improve bandwidth and processing time.
245+
Object masks are sent to the server and applied on the server side. Errors in the object mask format will lead to exceptions being thrown by the SoftLayer API. By carefully choosing an Object Mask, you can limit amount of information transferred from the server which may improve bandwidth and processing time.
236246

237247
You @object_with_id@ should only be called once in any calling sequence. You may call @object_mask@ multiple times, but the server may generate a warning if the Object Masks ask for duplicate properties of some object.
238248

examples/account_info.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@
2626

2727
begin
2828
softlayer_client = SoftLayer::Client.new(
29-
:username => "joecustomer" # enter your username here
30-
:api_key => "feeddeadbeefbadf00d..." # enter your api key here
29+
# :username => "joecustomer" # enter your username here
30+
# :api_key => "feeddeadbeefbadf00d..." # enter your api key here
3131
)
3232

33-
# use an account service to get a list of the open tickets and print their IDs and titles
33+
# Demonstrates using the low-level capabilities of the softlayer_api
34+
# gem to get directly at methods in the SoftLayer API and extract
35+
# data from them.
3436
account_service = softlayer_client['Account'];
3537
account = account_service.getObject
38+
3639
pp account
3740
rescue Exception => exception
3841
puts "Unable to retrieve account information: #{exception}"

examples/account_servers.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#
2+
# Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
3+
#
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
#
11+
# The above copyright notice and this permission notice shall be included in
12+
# all copies or substantial portions of the Software.
13+
#
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
# THE SOFTWARE.
21+
#
22+
23+
require 'rubygems'
24+
require 'softlayer_api'
25+
require 'pp'
26+
27+
# We can set the default client to be our client and that way
28+
# we can avoid supplying it later
29+
SoftLayer::Client.default_client = SoftLayer::Client.new(
30+
# :username => "joecustomer" # enter your username here
31+
# :api_key => "feeddeadbeefbadf00d..." # enter your api key here
32+
)
33+
34+
account = SoftLayer::Account.account_for_client()
35+
36+
# grab a list of all the servers on the account.
37+
servers = account.servers
38+
39+
# measure their fully qualified domain names so we can print a pretty table
40+
max_name_len = servers.inject(0) { |max_name, server| [max_name, server.fullyQualifiedDomainName.length].max }
41+
42+
printf "%#{-max_name_len}s\tPrimary Public IP\n", "Server FQDN"
43+
printf "%#{-max_name_len}s\t-----------------\n", "-----------"
44+
45+
servers.each do |server|
46+
ip_field = server.primary_public_ip ? server.primary_public_ip : "No Public Interface"
47+
printf "%#{-max_name_len}s\t#{ip_field}\n", server.fullyQualifiedDomainName
48+
end

examples/create_ticket.rb

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,33 +24,44 @@
2424
require 'softlayer_api'
2525
require 'pp'
2626

27-
# We're creating more than one service so we'll use the globals to establish
28-
# the username and API key.
29-
$SL_API_USERNAME = "joecustomer" # enter your username here
30-
$SL_API_KEY = "feeddeadbeefbadf00d..." # enter your api key here
27+
softlayer_client = SoftLayer::Client.new(
28+
# :username => "joecustomer" # enter your username here
29+
# :api_key => "feeddeadbeefbadf00d..." # enter your api key here
30+
)
3131

32-
softlayer_client = SoftLayer::Client.new()
3332
begin
34-
# use an account service to get the account ID of my account
35-
account_service = softlayer_client.service_named("Account")
36-
my_account_id = account_service.getCurrentUser['id']
33+
# To create a ticket we have to assign the ticket to some user so
34+
# assign our new ticket to the current user
35+
account = SoftLayer::Account.account_for_client(softlayer_client)
36+
account_user = account.service.getCurrentUser
37+
my_user_id = account_user["id"]
38+
39+
# We also need a subject for the ticket. Subjects are specified by id
40+
# This code prints out a table of all the ticket subjects with their
41+
# ids:
42+
ticket_subjects = SoftLayer::Ticket.ticket_subjects(softlayer_client)
43+
ticket_subjects.each do |subject|
44+
puts "#{subject['id']}\t#{subject['name']}"
45+
end
46+
47+
# For this example we'll use 'Public Network Question' as the subject. That's id 1022
48+
public_network_question_id = 1022
3749

38-
# Use a ticket service to create a standard support ticket, assigned to me.
39-
# Note: calling for the Ticket service using the brackets is entirely equivalent
40-
# go calling service_named('Ticket')
41-
ticket_service = softlayer_client['Ticket']
42-
new_ticket = ticket_service.createStandardTicket(
43-
{
44-
"assignedUserId" => my_account_id,
45-
"subjectId" => 1022,
46-
"notifyUserOnUpdateFlag" => true
47-
},
48-
"This is a test ticket created from a Ruby client")
50+
# A title is optional, but we'll provide one and we offer the body of the ticket
51+
# remember to pass the client to create_standard_ticket
52+
new_ticket = SoftLayer::Ticket.create_standard_ticket(
53+
:client => softlayer_client,
54+
:title => "This is a test ticket, please simply close it",
55+
:body => "This test ticket was created to test the Ruby API client. Please ignore it.",
56+
:subject_id => public_network_question_id,
57+
:assigned_user_id => my_user_id
58+
)
4959

50-
puts "Created a new ticket : #{new_ticket['id']} - #{new_ticket['title']}"
60+
puts "Created a new ticket : #{new_ticket.id} - #{new_ticket.title}"
61+
62+
# we can also add an update to the ticket:
63+
new_ticket.update("This is a ticket update sent from the Ruby library")
5164

52-
# add an update to the newly created ticket.
53-
pp ticket_service.object_with_id(new_ticket['id']).edit({}, "This is a ticket update sent from the Ruby library")
5465
rescue Exception => exception
5566
$stderr.puts "An exception occurred while trying to complete the SoftLayer API calls #{exception}"
5667
end

examples/open_tickets.rb

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,22 @@
2424
require 'softlayer_api'
2525
require 'pp'
2626

27-
$SL_API_USERNAME = "joecustomer" # enter your username here
28-
$SL_API_KEY = "feeddeadbeefbadf00d..." # enter your api key here
27+
# One way to provide a username and api key is to provide them
28+
# as globals.
29+
# $SL_API_USERNAME = "joecustomer" # enter your username here
30+
# $SL_API_KEY = "feeddeadbeefbadf00d..." # enter your api key here
2931

30-
softlayer_client = SoftLayer::Client.new()
32+
# The client constructed here must get it's credentials from somewhere
33+
# In this script you might uncomment the globals above and assign your
34+
# credentials there
35+
SoftLayer::Client.default_client = SoftLayer::Client.new()
3136

32-
# use an account service to get a list of the open tickets and print their
33-
# IDs and titles
34-
account_service = softlayer_client.service_named("Account")
37+
# The openTickets routine will pick up the default client established above.
38+
open_tickets = SoftLayer::Ticket.open_tickets()
3539

36-
open_tickets = account_service.getOpenTickets
37-
open_tickets.each { |ticket| puts "#{ticket['id']} - #{ticket['title']}" }
38-
39-
# Now use the ticket service to get a each ticket (by ID) and a subset of the
40-
# information known about it. We've already collected this information above,
41-
# but this will demonstrate using an object mask to filter the results from
42-
# the server.
43-
ticket_service = softlayer_client["Ticket"]
40+
open_tickets.sort!{ |lhs, rhs| -(lhs.lastEditDate <=> rhs.lastEditDate) }
4441
open_tickets.each do |ticket|
45-
begin
46-
pp ticket_service.object_with_id(ticket["id"]).object_mask("mask[id,title,createDate,modifyDate,assignedUser[id,username,email]]").getObject
47-
rescue Exception => exception
48-
puts "exception #{exception}"
49-
end
42+
printf "#{ticket.id} - #{ticket.title}"
43+
44+
ticket.has_updates? ? printf("\t*\n") : printf("\n")
5045
end

0 commit comments

Comments
 (0)