Project

General

Profile

API v2 Development Guidelines » History » Version 2

Tomáš Strachota, 10/15/2014 07:40 AM

1 1 Tomáš Strachota
h1. API v2 Development Guidelines
2
3
4
h2. Documentation
5
6
Foreman's API uses "ApiPie":https://github.com/Apipie/apipie-rails documentation framework. Our cli project "Hammer":https://github.com/theforeman/hammer-cli relies heavily on the data exported from the documentation. It is therefore important to keep the documentation consistent.
7
8
h3. Basic ApiPie features
9
10
Please see "ApiPie's official documentation":https://github.com/Apipie/apipie-rails#documentation to get to know the basics of it's dsl language.
11
12
h3. Available parameter types
13
14
ApiPie uses validators for checking parameter types. Although this feature is currently disabled on the server side it's still worth setting the validators correctly. Firstly the validator description propagates to the html rendered docs and makes it easier to understand the parameters (e.g. the docs list all acceptable values for enum types). Secondly hammer CLI reuses the validator information when validating command line options.
15
16
There are some frequent validators that are worth mentioning:
17
18
|_. name |_. validator                |_. description                     |_. example usage |
19
| Type   | String, Fixnum, :bool, ... | simply checks if the type matches | <pre><code class="ruby">
20
param :name, String,
21
  :required => true,
22
  :desc => N_("Interface name")</code></pre> |
23
| Enum   | any array of values        | check if parameter value is included in a given array | <pre><code class="ruby">
24
param :mode, Nic::Bond::MODES</code></pre> |
25
| Hash   | Hash                       | allows to describe inner fields of the hash | <pre><code class="ruby">
26
param :interface, Hash do
27
    param :mac, String
28
    param :ip, String
29
end</code></pre> |
30
| Array  | Array                      | can check for types (:of) and values (:in) of the items | <pre><code class="ruby">
31
param :colors, Array,
32
  :of => String,
33
  :in => ["red", "green", "blue"]</code></pre> |
34
35
See "ApiPie's docs":https://github.com/Apipie/apipie-rails#validators more validators.
36
37
38
h3. Required options
39
40
Unfortunately ApiPie does not allow to specify conditional requirements or dependencies amongst the parameters. Only a single parameter can be required. This is an important thing to bear in mind. Only the parameters mandatory at any conditions can therefore be set as required.
41
42
In cases when one parameter depends on another it is a good practice to mention the dependency in the description.
43
<pre><code class="ruby">
44
# E.g.
45
param :type, Nic::TYPES, :required => true, :desc => N_("Interface type, e.g: Nic::BMC")
46
param :mode, Nic::Bond::MODES, :desc => N_("Bond mode of the interface, e.g. balance-rr. Only for bond interfaces.")
47
</code></pre>
48
49
h3. Description styles
50
51
Both action and parameter descriptions should start with capital letters. Because of the lacking conditional requirements it is a good practise to put a note when the parameter is required or allowed only at certain circumstances.
52
All descriptions must be wrapped with 'N_(...)' to mark them for translation. They are used for building CLI's help.
53
54
55
h3. Available param groups
56
57
There are some predefined parameter groups for params commonly used accross the controllers.
58
59
|_. group name            |_. usage |
60
| :pagination             | for index actions, contains fields: page, per_page |
61
| :search_and_pagination  | for index actions,contains fields: page, per_page, search, order |
62
| :taxonomies             | for creating/updating taxable resources, contains fields: location_ids, organization_ids |
63
| :taxonomy_scope         | for index actions scoped in a taxonomy, contains fields: location_id, organization_id |
64
65
<pre><code class="ruby">
66
# Example usage:
67
param_group :pagination, ::Api::V2::BaseController
68
</code></pre>
69
70
71
h2. Parameters
72
73
h3. Nesting
74
75
API parameters related to a resource (usually in create and update actions) need to be nested in a root node named by the resource.
76
<pre><code class="json">
77
{
78 2 Tomáš Strachota
  "architecture": {
79
    "name": "i386"
80 1 Tomáš Strachota
  }
81
}
82
</code></pre>
83
84
85
h2. Responses
86
87
API uses "rabl":https://github.com/nesquena/rabl/ templating language for describing the output.
88
The templates are stored in views/api/v2/. All API output should be rendered via templates.
89
90
h3. Template file organization
91
92
Each resource has two fundamental templates:
93
* base.json.rabl - Basic info about the resource, contains usually only identifiers. It's used for rendering references to the resource.
94
* main.json.rabl - Inherits from 'base', contains all attributes apart from references.
95
96
In addition tho that resources typically define templates for standard controller actions:
97
* show.json.rabl - Used for actions show and delete, inherits from 'main' and adds references to related resources.
98
* index.json.rabl - Used for listing, inherits from 'main'.
99
* create.json.rabl - Used for create and update actions, inherits from 'show'.
100
101
102
h3. Formatting errors
103
104
Errors have also their own rabl layout and templates. Please avoid rendering error jsons directly. Base controller's method
105
render_error can help selecting correct rabl template.
106
107
<pre><code class="ruby">
108
render_error('unauthorized', :status => :unauthorized, :locals => { :user_login => @user.login })
109
render_error('unprocessable_entity', :status => :unprocessable_entity)
110
</code></pre>
111
112
Available error templates (placed in views/api/v2/errors/) are:
113
* access_denied
114
* not_found
115
* param_error
116
* standard_error
117
* unauthorized
118
* unprocessable_entity
119
* unsupported_content_type
120
121
122
h3. Formatting index reponses
123
124
Index responses use custom layout with some useful metadata. Standard controllers fill the metadata itself from received parameters and activerecord data.
125
Corner cases may require to tweak the values by hand. Following controller variables can be set to change the default metadata values:
126
127
<pre><code class="ruby">
128
# Pagination
129
@total    # total number of items in the collection
130
@per_page # entries per page, usually set by params[:per_page]
131
@page     # number of the displayed page
132
133
# Search
134
@subtotal # only for searches, number of items found
135
@search   # elastic search query
136
137
# Ordering
138
@order # 'ASC', 'DESC'
139
@by    # field name
140
</code></pre>
141
142
h3. Overriding the default template layout
143
144
Index layout is by default used only for actions named 'index'. You can force rabl to use the layout also in other actions that list resources:
145
146
<pre><code class="ruby">
147
render :your_template_for_the_action, :layout => 'api/v2/layouts/index_layout'
148
</code></pre>