Class: Aspera::Cli::Plugins::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/cli/plugins/base.rb

Overview

Base class for command plugins

Direct Known Subclasses

Ats, BasicAuth, Config, Cos, Httpgw

Defined Under Namespace

Modules: Operations

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context:) ⇒ Base

Returns a new instance of Base.



30
31
32
33
34
35
36
# File 'lib/aspera/cli/plugins/base.rb', line 30

def initialize(context:)
  # Check presence in descendant of mandatory method and constant
  Aspera.assert(respond_to?(:execute_action), type: InternalError){"Missing method 'execute_action' in #{self.class}"}
  Aspera.assert(self.class.const_defined?(:ACTIONS), type: InternalError){"Missing constant 'ACTIONS' in #{self.class}"}
  @context = context
  add_manual_header if @context.man_header
end

Instance Attribute Details

#contextObject (readonly)

Global objects



39
40
41
# File 'lib/aspera/cli/plugins/base.rb', line 39

def context
  @context
end

Class Method Details

.declare_options(options) ⇒ Object



23
24
25
26
27
# File 'lib/aspera/cli/plugins/base.rb', line 23

def declare_options(options)
  options.declare(:query, 'Additional filter for for some commands (list/delete)', allowed: [Hash, Array, NilClass])
  options.declare(:bulk, 'Bulk operation (only some)', allowed: Allowed::TYPES_BOOLEAN, default: false)
  options.declare(:bfail, 'Bulk operation error handling', allowed: Allowed::TYPES_BOOLEAN, default: true)
end

Instance Method Details

#add_manual_header(has_options = true) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/aspera/cli/plugins/base.rb', line 56

def add_manual_header(has_options = true)
  # Manual header for all plugins
  options.parser.separator('')
  options.parser.separator("COMMAND: #{self.class.name.split('::').last.downcase}")
  options.parser.separator("SUBCOMMANDS: #{self.class.const_get(:ACTIONS).map(&:to_s).sort.join(' ')}")
  options.parser.separator('OPTIONS:') if has_options
end

#configAspera::Cli::Plugins::Config



46
# File 'lib/aspera/cli/plugins/base.rb', line 46

def config; @context.config; end

#do_bulk_operation(command:, descr: nil, values: Hash, id_result: 'id', fields: :default, schema: nil) {|param| ... } ⇒ Hash

For create and delete operations: execute one action or multiple if bulk is yes

Parameters:

  • command (Symbol)

    Operation: :create, :delete, ...

  • descr (String, nil) (defaults to: nil)

    Description of the value

  • values (Class, Array, Symbol) (defaults to: Hash)

    Type, or list of values, or :identifier, result is given to the block in loop

  • id_result (String) (defaults to: 'id')

    Key in result Hash to use as identifier

  • fields (Symbol, Array) (defaults to: :default)

    Fields to display

  • schema (Hash, nil) (defaults to: nil)

    JSON schema for validation

Yield Parameters:

  • param (Object)

    The parameter value to process

Yield Returns:

  • (Hash, nil)

    Result hash for the operation (optional)

Returns:

  • (Hash)

    Result suitable for CLI output



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/aspera/cli/plugins/base.rb', line 74

def do_bulk_operation(command:, descr: nil, values: Hash, id_result: 'id', fields: :default, schema: nil, &block)
  Aspera.assert(block_given?, 'missing block')
  is_bulk = options.get_option(:bulk)
  case values
  when :identifier
    values = options.instance_identifier(description: descr)
  when Class
    values = value_create_modify(command: command, description: descr, type: values, bulk: is_bulk, schema: schema)
  end
  # If not bulk, there is a single value
  params = is_bulk ? values : [values]
  Log.log.warn('Empty list given for bulk operation') if params.empty?
  Log.dump(:bulk_operation, params)
  result_list = []
  params.each do |param|
    # Init for delete
    result = {id_result => param}
    begin
      # Execute custom code
      res = yield(param)
      # If block returns a hash, let's use this (create)
      result = res if res.is_a?(Hash)
      # TODO: remove when faspio gw api fixes this
      result = res.first if res.is_a?(Array) && res.first.is_a?(Hash)
      # Create -> created
      result['status'] = "#{command}#{'e' unless command.to_s.end_with?('e')}d".gsub(/yed$/, 'ied')
    rescue StandardError => e
      raise e if options.get_option(:bfail)
      result['status'] = e.to_s
    end
    result_list.push(result)
  end
  display_fields = [id_result, 'status']
  if is_bulk
    return Result::ObjectList.new(result_list, fields: display_fields)
  else
    display_fields = fields unless fields.eql?(:default)
    return Result::SingleObject.new(result_list.first, fields: display_fields)
  end
end

#entity_execute(api:, entity:, command: nil, display_fields: nil, items_key: nil, delete_style: nil, id_as_arg: false, is_singleton: false, list_query: nil, schema: nil) {|value| ... } ⇒ Hash

Operations: Create, Delete, Show, List, Modify

Parameters:

  • api (Aspera::Rest)

    API to use

  • entity (String)

    Sub path in URL to resource relative to base url

  • command (Symbol, nil) (defaults to: nil)

    Command to execute: :create, :show, :list, :modify, :delete

  • display_fields (Array, nil) (defaults to: nil)

    Fields to display by default

  • items_key (String, nil) (defaults to: nil)

    Result is in a sub key of the JSON

  • delete_style (String, nil) (defaults to: nil)

    If set, the delete operation by array in payload

  • id_as_arg (Boolean, String) (defaults to: false)

    If set, the id is provided as url argument ?<id_as_arg>=

  • is_singleton (Boolean) (defaults to: false)

    If true, entity is the full path to the resource

  • list_query (Hash, nil) (defaults to: nil)

    Query parameters for list operation

Yield Parameters:

  • value (String)

    Value to search for identifier

Yield Returns:

Returns:

  • (Hash)

    Result suitable for CLI result



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/aspera/cli/plugins/base.rb', line 128

def entity_execute(
  api:,
  entity:,
  command: nil,
  display_fields: nil,
  items_key: nil,
  delete_style: nil,
  id_as_arg: false,
  is_singleton: false,
  list_query: nil,
  schema: nil,
  &block
)
  command = options.get_next_command(Operations::ALL) if command.nil?
  if is_singleton
    one_res_path = entity
  elsif Operations::INSTANCE.include?(command)
    one_res_id = options.instance_identifier(&block)
    one_res_path = "#{entity}/#{one_res_id}"
    one_res_path = "#{entity}?#{id_as_arg}=#{one_res_id}" if id_as_arg
  end

  case command
  when :create
    raise BadArgument, 'cannot create singleton' if is_singleton
    return do_bulk_operation(command: command, descr: 'data', fields: display_fields, schema: schema) do |params|
      api.create(entity, params)
    end
  when :delete
    raise BadArgument, 'cannot delete singleton' if is_singleton
    if !delete_style.nil?
      one_res_id = [one_res_id] unless one_res_id.is_a?(Array)
      Aspera.assert_type(one_res_id, Array, type: Cli::BadArgument)
      api.delete(
        entity,
        nil,
        content_type: Mime::JSON,
        body:         {delete_style => one_res_id}
      )
      return Result::Status.new('deleted')
    end
    return do_bulk_operation(command: command, values: one_res_id) do |one_id|
      api.delete("#{entity}/#{one_id}", query_read_delete)
      {'id' => one_id}
    end
  when :show
    return Result::SingleObject.new(api.read(one_res_path), fields: display_fields)
  when :list
    data, http = api.read(entity, query_read_delete, ret: :both)
    return Result::Empty.new if http.code == '204'
    # TODO: not generic : which application is this for ?
    if http['Content-Type'].start_with?('application/vnd.api+json')
      Log.log.debug('is vnd.api')
      data = data[entity]
    end
    data = data[items_key] if items_key
    case data
    when Hash
      return Result::SingleObject.new(data, fields: display_fields)
    when Array
      return Result::ObjectList.new(data, fields: display_fields) if data.empty? || data.first.is_a?(Hash)
      return Result::ValueList.new(data)
    else
      Aspera.error_unexpected_value(data.class.name){'list type'}
    end
  when :modify
    parameters = value_create_modify(command: command, schema: schema)
    api.update(one_res_path, parameters)
    return Result::Status.new('modified')
  else
    Aspera.error_unexpected_value(command){'command'}
  end
end

#formatterAspera::Cli::Formatter



48
# File 'lib/aspera/cli/plugins/base.rb', line 48

def formatter; @context.formatter; end

#http_configAspera::Cli::Http

Returns:



54
# File 'lib/aspera/cli/plugins/base.rb', line 54

def http_config; @context.http_config; end

#optionsAspera::Cli::Manager



42
# File 'lib/aspera/cli/plugins/base.rb', line 42

def options; @context.options; end

#persistencyAspera::PersistencyFolder



50
# File 'lib/aspera/cli/plugins/base.rb', line 50

def persistency; @context.persistency; end

#presetsAspera::Cli::PresetManager



52
# File 'lib/aspera/cli/plugins/base.rb', line 52

def presets; @context.presets; end

#query_read_delete(default: nil) ⇒ Hash?

Query parameters in URL suitable for REST: list/GET and delete/DELETE

Parameters:

  • default (Hash, nil) (defaults to: nil)

    Default query parameters

Returns:

  • (Hash, nil)

    Query parameters



205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/aspera/cli/plugins/base.rb', line 205

def query_read_delete(default: nil)
  # Dup default, as it could be frozen
  query = options.get_option(:query) || default.dup
  Log.log.debug{"query_read_delete=#{query}".bg_red}
  begin
    # Check it is suitable
    URI.encode_www_form(query) unless query.nil?
  rescue StandardError => e
    raise Cli::BadArgument, "Query must be an extended value (Hash, Array) which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
  end
  return query
end

#transferAspera::Cli::TransferAgent



44
# File 'lib/aspera/cli/plugins/base.rb', line 44

def transfer; @context.transfer; end

#value_create_modify(command:, description: nil, type: Hash, bulk: false, default: nil, schema: nil) ⇒ Hash+

Retrieves an extended value from command line. Used for creation or modification of entities.

Parameters:

  • command (Symbol)

    Command name for error message

  • description (String, nil) (defaults to: nil)

    Description of the value

  • type (Class, nil) (defaults to: Hash)

    Expected type of value

  • bulk (Boolean) (defaults to: false)

    If true, value must be an Array of type

  • default (Object, nil) (defaults to: nil)

    Default value if not provided

  • schema (Hash, nil) (defaults to: nil)

    JSON schema for validation

Returns:

  • (Hash, Array<Hash>)

    The value(s) to create object(s)



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/aspera/cli/plugins/base.rb', line 227

def value_create_modify(command:, description: nil, type: Hash, bulk: false, default: nil, schema: nil)
  value = options.get_next_argument(
    "parameters for #{command}#{" (#{description})" unless description.nil?}",
    mandatory: default.nil?,
    validation: bulk ? Array : type,
    schema: schema
  )
  value = default if value.nil?
  unless type.nil?
    Aspera.assert_type(type, Class){'type'}
    if bulk
      Aspera.assert_array_all(value, type, type: Cli::BadArgument){'type'}
    else
      Aspera.assert_type(value, type, type: Cli::BadArgument){'type'}
    end
  end
  return value
end