module ApiResources class Instances include Praxis::EndpointDefinition media_type Instance version '1.0' # :show action is the canonical path for this resource. # Note that the following is redundant, since :show is the default canonical path if none is defined. canonical_path :show prefix '/clouds/:cloud_id/instances' trait :authenticated action_defaults do requires_ability :read params do attribute :cloud_id, Integer, required: true, min: 0 end end action :index do routing do get '' end headers do # BOTH ARE EQUIVALENT #key "FOO", String, required: true header "FOO", /bar/ key 'Account-Id', Integer, required: false, min: 0 end params do attribute :response_content_type, String, default: 'application/vnd.acme.instance;type=collection' end response :ok, Praxis::Collection.of(Instance) end action :show do routing do get '/:id' end response :ok, media_type: 'application/json' response :unauthorized params do attribute :id, required: true attribute :junk, String, default: '' attribute :some_date, DateTime, default: DateTime.parse('2012-12-21') attribute :fail_filter, Attributor::Boolean, default: false attribute :create_identity_map, Attributor::Boolean, default: false end payload required: false, null: true do attribute :something, String attribute :optional, String, default: "not given" end end action :bulk_create do routing do post '' end payload Praxis::Types::MultipartArray do name_type Integer payload_type Instance end response :multipart_ok, Praxis::Types::MultipartArray do name_type Integer part /\d+/ do header 'Status', '201' header 'Content-Type', /^#{Instance.identifier}/ header 'Location', Attributor::URI, example: proc { |part| ApiResources::Instances.to_href(cloud_id: part[:value].cloud_id, id: part[:value].id) } payload Hash do attribute :key, Integer, required: true attribute :value, Hash, required: true, reference: Instance do attribute :id attribute :name end end end end # Using a hash param for parts #response :multipart_ok, parts: { # like: :created, # location: /\/instances\// #} # Using a block for parts to defin a sub-request # sub_request = proc do # status 201 # media_type Instance # headers ['X-Foo','X-Bar'] # end # response :bulk_response, parts: sub_request end action :attach_file do routing do post '/:id/files' end params do attribute :id end payload Praxis::Types::MultipartArray do part 'destination_path', String, required: true file 'file', Attributor::Tempfile, required: false part(/.*/, String) # Allows extra parts end response :ok, media_type: 'application/json' response :validation_error # TODO: include this by default, or rethink. end action :terminate do routing do any '/:id/terminate' end requires_ability :terminate params do attribute :id end payload required: false, null: true do attribute :when, DateTime end response :ok, media_type: 'application/json' end action :stop do routing do post '/:id/stop' end requires_ability :stop params do attribute :id end response :ok, media_type: 'application/json' end action :update do routing do patch '/:id' end params do attribute :id, required: true end payload do attribute :name, regexp: /.*/ attribute :root_volume end response :ok end action :exceptional do routing do prefix '//clouds/:cloud_id/otherinstances' get '/_action/*', except: '*/_action/exceptional' end params do attribute :splat, Attributor::Collection.of(String), required: true end response :ok, media_type: 'application/json' end # OTHER USAGES: # note: these are all hypothetical, pending, brainstorming usages. # given: single file, super simple upload, with count constraint # result: only one part is accepted # example: # payload Praxis::Multipart.of(FileUpload), count: 1 # given: multiple file uploads # example: # payload Praxis::Multipart.of(key: UUID, value: Attributor::FileUpload) # given: any untyped multipart request body # example: # payload Praxis::Multipart # given: single known key, plus multiple uploaded files which can take any name # result: multiple files collected into a single Hash.of(value: FileUpload) # example: # payload Praxis::Multipart do # key 'destination', String, required: true # splat 'remaining', Hash.of(value: FileUpload) # end # given: single known key, plus multiple uploaded files which can take any name # result: file parts coerced to FileUpload # example: # payload Praxis::Multipart do # key 'destination', String, required: true # other_keys FileUpload # end # given: single known key, plus multiple uploaded files, with names like 'file-' # result: file parts coerced to FileUpload # example: # payload Praxis::Multipart do # key 'destination', String, required: true # match /file-.+/, FileUpload # end end end