#!/usr/bin/env ruby # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The # ASF licenses this file to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance with the # License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. require 'rubygems' require 'optparse' require 'uri' require 'deltacloud' require 'plain_formatter' include DeltaCloud::PlainFormatter options = { :verbose => false } @optparse = OptionParser.new do |opts| opts.banner = < e invalid_usage(e.message) end # First try to get API_URL from environment options[:api_url] = ENV['API_URL'] if options[:api_url].nil? if(options[:api_url].nil?) invalid_usage("You must supply the url to the deltacloud api; either use '-u' flag or set the 'API_URL' environment variable") end url = URI.parse(options[:api_url]) api_url = "http://#{url.host}#{url.port ? ":#{url.port}" : ''}#{url.path}" options[:collection] = ARGV[0] options[:operation] = ARGV[1] # Connect to Deltacloud API and fetch all entry points client = DeltaCloud.new(url.user || ENV['API_USER'], url.password || ENV['API_PASSWORD'], api_url) collections = client.entry_points.keys # Exclude collection which don't have methods in client library yet collections.delete(:instance_states) #add blob collection if buckets is present collections << :blob if collections.include?(:buckets) # If list parameter passed print out available collection # with API documentation if options[:list] and options[:collection].nil? collections.each do |c| puts sprintf("%-22s", c.to_s[0, 22]) end exit(0) end # If collection parameter is present and user requested list # print all operation defined for collection with API documentation if options[:list] and options[:collection] #deal with blobs again - bypass 'normal' docs procedure if options[:collection] =~ /blob/i puts "create \t\t: Create a new blob in a specified bucket (POST /api/buckets/:bucket)" puts "destroy \t: Delete a specified blob in a specified bucket (DELETE /api/buckets/:bucket/:blob)" puts "show \t\t: Get details of a specified blob in a specified bucket (GET /api/buckets/:bucket/:blob)" puts "data \t\t: Get the contents of a specified blob - the blob data content itself" exit(0) end doc = client.documentation(options[:collection]) doc.operations.each do |c| puts sprintf("%-20s: %s", c.operation, c.description) end exit(0) end if options[:version] puts "Deltacloud API(#{client.driver_name}) 0.1" exit(0) end # List items from collection (typically /instances) # Do same if 'index' operation is set if options[:collection] and ( options[:operation].nil? or options[:operation].eql?('index') ) invalid_usage("Unknown collection: #{options[:collection]}") unless collections.include?(options[:collection].to_sym) #cannot list blobs - can only show a specific blob invalid_usage("You must specify a particular blob with -i and a particular bucket with -b") if options[:collection] =~ (/blob/i) params = {} params.merge!(:architecture => options[:architecture]) if options[:architecture] params.merge!(:id => options[:id]) if options[:id] params.merge!(:state => options[:state]) if options[:state] client.send(options[:collection].to_s, params).each do |model| puts format(model) end exit(0) end if options[:collection] and options[:operation] invalid_usage("Unknown collection: #{options[:collection]}") unless collections.include?(options[:collection].to_sym) params = {} params.merge!(:id => options[:id]) if options[:id] # If collection is set and requested operation is 'show' just 'singularize' # collection name and print item with specified id (-i parameter) #Blobs are a special case so deal with first - if options[:collection] =~ (/blob/i) invalid_usage("Please specify the bucket for this blob using the -b option") unless options[:bucket_id] invalid_usage("Missing blob ID, please specify with -i option") unless options[:id] params = {} params.merge!(:id => options[:id], 'bucket' => options[:bucket_id]) params.merge!('metadata'=>options[:blob_metadata]) unless options[:blob_metadata].nil? case options[:operation] when 'show' then puts format(client.send( options[:collection], params)) when 'data' then puts client.blob_data(params) when 'create' then invalid_usage("Specify the location of the new blob data (full local path) using -f option") unless options[:file_path] params.merge!('file_path'=>options[:file_path]) blob = client.create_blob(params) puts format(blob) when 'destroy' then client.destroy_blob(params) else invalid_usage("Please specify a valid operation for the blob collection - try -l to see available operations") end exit(0) end if options[:operation].eql?('show') invalid_usage("Missing ID, must be provided with --id") unless options[:id] puts format(client.send(options[:collection].gsub(/s$/, ''), options[:id])) exit(0) end # If collection is set and requested operation is create new instance, # --image-id, --hardware-profile and --name parameters are used # Returns created instance in plain form if options[:collection].eql?('instances') and options[:operation].eql?('create') invalid_usage("Missing image-id") unless options[:image_id] if options[:name] and ! client.feature?(:instances, :user_name) invalid_usage("Driver does not support user-supplied name") end params.merge!(:name => options[:name]) if options[:name] params.merge!(:image_id => options[:image_id]) if options[:image_id] params.merge!(:hwp_id => options[:hwp_id]) if options[:hwp_id] instance = client.create_instance(options[:image_id], params) puts format(instance) exit(0) end #Create and Destroy a bucket - require the bucket id: if options[:collection].eql?('buckets') if options[:operation].eql?('create') invalid_usage("Please specify an id for the new bucket with -i") unless options[:id] bucket = client.create_bucket('id'=>options[:id], 'bucket_location'=>options[:bucket_location]) puts format(bucket) elsif options[:operation].eql?('destroy') invalid_usage("Please specify the bucket you wish to destroy with -i") unless options[:id] client.destroy_bucket('id'=>options[:id]) else invalid_usage("Please specify a valid operation on buckets - use -l to see valid operations") end exit(0) end # All other operations above collections is done there: if options[:collection].eql?('instances') instance = client.instance(options[:id]) instance.send("#{options[:operation]}!".to_s) instance = client.instance(options[:id]) puts format(instance) exit(0) end end # If all above passed (eg. no parameters) puts @optparse