Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Basic Specification for SDK

Vishrut Shah edited this page Oct 12, 2016 · 2 revisions

Azure SDK for Ruby

The goal of this project is to expose the services provided by the Azure REST API in a Ruby language specific library to ease the use of the API for Ruby developers.

Design Considerations

This project is part of a larger project to create SDKs in many popular languages. There are a number of other SDKs already in existence for other languages. The ultimate goal is to have reasonable consistency between all of these libraries, both in what functionality is supported, and in the structure and style of the code. This includes terminology, naming of classes and methods, order of parameters, comments and documentation, and many other factors.

Further, as this library will ultimately be provided as an official Microsoft SDK, and since it will be open sourced, it is important to have a high level of code quality and an appropriate tone in the comments and documentation.

Requirements

Operating Systems Support

  • Mac OS/X 10.7 and later
  • Ubuntu 11.10 and later
  • Windows 7 and later

Ruby Framework Version Support

  • 2.0.0 +

Style Considerations

  • Code should follow the Github Style Guide for Ruby
  • Comments should not refer to Microsoft in the third person
  • Attention should be paid to licensing considerations when incorporating third-party code

API

The library should be organized into at minimum, two discrete layers: Communication Layer, Service Layer.

The Communication Layer should contain primitives used for interacting with the REST API. Higher level classes should use these classes, and not deal with the underlying HTTP protocol directly.

Example:

request = HttpRequest.new(uri, :post, "Some Data")
response = request.call

if response.success
  puts "#{response.status_code} - #{response.body}"
else
  puts "#{response.status_code} - Error!! #{response.body}"
end  

The Service Layer organizes groups of Azure services into proxy objects which use the Communication Layer objects to implement a standardized API of blocking method calls. The return values are simple data transfer objects (DTOs) such as a XML or JSON graph, a Hash, or possibly hand coded databag style DTOs.

Example:

service = BlobService.new

blob = service.get_blob(container_name, blob_name)
puts blob[:name]

Communication Layer API

HTTPRequest

Represents a HTTP request can perform synchronous queries to HTTP server, returning a HttpResponse

Attributes:

  • Host - The host name to connect to
  • Method - The method to use to connect (string such as GET, POST, PUT, etc...)
  • Path - The uri fragment
  • Query - Query parameters specified as a list of (name, value) pairs
  • Headers - Header values specified as (name, value) pairs
  • Body - The body of the request (stream or string)

Methods:

  • Call - Sends request to HTTP server and returns a HttpResponse
  • WithFilter filter - Applies a HttpFilter to the HTTP Pipeline

HTTPResponse

Represents a response from an HTTP request, including error information and streaming response data

Attributes:

  • StatusCode - The status code of the response
  • Success - Returns true if the status code is between 200 and 399, otherwise false
  • Headers - The returned headers, as a list of (name, value) pairs
  • Body - The body of the response (stream or string)

Methods: None

HTTPError

HTTP Exception when response status code >= 300

Attributes:

  • Message - The error message
  • StatusCode - The HTTP status code
  • ResponseHeader - The the response headers
  • ResponseBody - The the response body

Methods: None

HttpFilter

A filter which can modify the HTTP pipeline both before and after requests/responses. Multiple filters can be nested in a "Russian Doll" model to create a compound HTTP pipeline.

Attributes: None

Methods:

  • Call request, next - Executes the filter. next is a subsequent HttpFilter which must have it's Call method executed within each filter to complete the pipeline. This method should return an HttpResponse.

RetryPolicy

A HttpFilter implementation that handles retrying based on a specific policy when HTTP layer errors occur

Methods:

  • ShouldRetry response, retryData - Determines if the operation should be retried based on the provided HttpResponse and the retryData value which contains state information about the current retry scope.

Service Layer API

BlobService

Attributes: None

Methods:

  • GetServiceProperties
  • SetServiceProperties serviceProperties
  • ListContainers
  • CreateContainer container
  • DeleteContainer container
  • GetContainerProperties container
  • GetContainerMetadata container
  • GetContainerAcl container
  • SetContainerAcl container, acl
  • SetContainerMetadata container, metadata
  • ListBlobs container
  • CreatePageBlob container, blob, length
  • CreateBlockBlob container, blob, content
  • ClearBlobPages container, blob, range
  • CreateBlobPages container, blob, range, content
  • CreateBlobBlock container, blob, blockId, content
  • CommitBlobBlocks container, blob, blockList
  • ListBlobBlocks container, blob
  • GetBlobProperties container, blob
  • GetBlobMetadata container, blob
  • ListPageBlobRanges container, blob
  • SetBlobProperties container, blob
  • SetBlobMetadata container, blob, metadata
  • GetBlob container, blob
  • DeleteBlob container, blob
  • CreateBlobSnapshot container, blob
  • CopyBlob destinationContainer, destinationBlob, sourceContainer, sourceBlob
  • AcquireLease container, blob
  • RenewLease container, blob, leaseId
  • ReleaseLease container, blob, leaseId
  • BreakLease container, blob, leaseId

QueueService

Attributes: None

Methods:

  • ListQueues
  • ClearMessages queueName
  • CreateMessage queueName, messageText
  • CreateQueue queueName
  • DeleteMessage queueName, messageId, popReceipt
  • DeleteQueue queueName
  • GetQueueMetadata queueName
  • GetServiceProperties
  • ListMessages queueName
  • PeekMessages queueName
  • SetQueueMetadata queueName, metadata
  • SetServiceProperties serviceProperties
  • UpdateMessage queueName, messageId, popReceipt, messageText, visibilityTimeoutInSeconds

TableService

Attributes: None

Methods:

  • GetServiceProperties
  • SetServiceProperties serviceProperties
  • QueryTables
  • CreateTable table
  • GetTable table
  • DeleteTable table
  • QueryEntities table
  • InsertEntity table, entity
  • InsertOrMergeEntity table, entity
  • InsertOrReplaceEntity table, entity
  • UpdateEntity table, entity
  • MergeEntity table, entity
  • DeleteEntity table, partitionKey, rowKey
  • GetEntity table, partitionKey, rowKey
  • Batch batchOperations

ServiceBusService

Attributes: None

Methods:

  • SendMessage path, brokeredMessage
  • SendQueueMessage queueName, brokeredMessage
  • ReceiveQueueMessage queueName
  • ReceiveMessage path
  • SendTopicMessage topicName, brokeredMessage
  • ReceiveSubscriptionMessage topicName, subscriptionName
  • UnlockMessage brokeredMessage
  • DeleteMessage brokeredMessage
  • CreateQueue queueInfo
  • DeleteQueue queuePath
  • GetQueue queuePath
  • ListQueues
  • CreateTopic topicInfo
  • DeleteTopic topicPath
  • GetTopic topicPath
  • ListTopics
  • CreateSubscription topicPath, subscriptionInfo
  • DeleteSubscription topicPath, subscriptionName
  • GetSubscription topicPath, subscriptionName
  • ListSubscriptions topicPath
  • CreateRule topicPath, subscriptionName, ruleInfo
  • DeleteRule topicPath, subscriptionName, ruleName
  • GetRule topicPath, subscriptionName, ruleName
  • ListRules topicPath, subscriptionName

ServiceManagementService (optional)

Attributes: None

Methods:

  • ListStorageServices
  • GetStorageServiceProperties name
  • GetStorageServiceKeys name
  • RegenerateStorageServiceKeys name, keyType
  • CreateStorageService name, label, options
  • DeleteStorageService name
  • UpdateStorageService name, options
  • ListAffinityGroups
  • CreateAffinityGroup name, label, location
  • DeleteAffinityGroup name
  • UpdateAffinityGroup name, label
  • GetAffinityGroupProperties name
  • ListLocations
  • GetOperationStatus requestInfo
  • ListHostedServices
  • CreateHostedService name, label, options
  • UpdateHostedService name, options
  • DeleteHostedService name
  • GetHostedServiceProperties name
  • CreateDeployment name, deploymentName, slot, packageUrl, configuration, label
  • GetDeployment name, options
  • SwapDeployment name, source, destination
  • DeleteDeployment name, options
  • ChangeDeploymentConfiguration name, configuration, options
  • UpdateDeploymentStatus name, status, options
  • UpgradeDeployment name, mode, packageUrl, configuration, label, force, options
  • WalkUpgradeDomain name, upgradeDomain, options
  • RebootRoleInstance name, roleName, options
  • ReimageRoleInstance name, roleName, options
  • RollbackUpdateOrUpgrade name, mode, force, options

Optional Features

The requirements section lists the minimum required features for the SDK. In addition to those requirements there are some common optional feature that may be implemented.

Convenience Layer

A Convenience Layer is another layer of abstraction above the Service Layer which adds additional domain-level business logic and entity semantics to the resources accessed via the Service Layer API. This can take many forms, but a common abstraction is to create entities such as Blob, Table, Queue etc, with CRUD methods like create, read, update, delete, or something like this snippet:

queue = Queue.find(queue_name)
message = queue.pop
puts message.text

as opposed to:

service = QueueService.new
raw_message = service.GetMessages(queue_name, { :numofmessage=>1, :visibilitytimeout=>1})
document = Nokogiri::XML(response.body)
message_text = ''
(document / "//QueueMessagesList/QueueMessage").map do |node|
  message_text = (node % "MessageText").text
end
puts message_text

This layer can also include additional semantics like equality comparisons, tracking changed state to determine if a storage update call is necessary, and client-side validation of input (to avoid costly service calls to determine validity). Putting such validation in the Convenience Layer instead of the Service Layer allows the REST API the change it's validation rules, and the Service Layer will continue to work, where the Convenience Layer may not. In such a situation, where changes in the REST API cause validations in the client library to break, having a validation-free Service Layer allows an end user to bypass the Convenience Layer and write work-around code against the Service Layer, without the need for the SDK to be updated and deployed immediately.

API Example

The PAI for the convenience layer will vary significantly with the preferred idioms of the language it's written for. Ruby may have very different preferences from Java in terms of how the object model is structured, etc. Of course, having consistency across the SDKs is good, but in this layer, it is less important than creating a very natural and idiomatic surface area for the developer to use.

Here's an example API that could be used across multiple languages:

** TODO: document convenience layer API from .NET/Ruby/etc. **