Module: Cyclid::API::Organizations::Jobs

Defined in:
app/cyclid/controllers/organizations/job.rb

Overview

API endpoints for Organization Jobs

Organizations collapse

Class Method Summary collapse

Class Method Details

.registered(app) ⇒ Object

Sinatra callback



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'app/cyclid/controllers/organizations/job.rb', line 105

def self.registered(app)
  include Errors::HTTPErrors
  include Constants::JobStatus

  # Return a list of jobs
  app.get do
    authorized_for!(params[:name], Operations::READ)

    org = Organization.find_by(name: params[:name])
    halt_with_json_response(404, INVALID_ORG, 'organization does not exist') \
      if org.nil?

    # Get any search terms that we'll need to find the appropriate jobs
    search = {}
    search[:job_name] = URI.decode(params[:s_name]) if params[:s_name]
    search[:status] = params[:s_status] if params[:s_status]

    # search_from & search_to should be some parsable format
    if params[:s_from] and params[:s_to]
      from = Time.parse(params[:s_from])
      to = Time.parse(params[:s_to])

      # ActiveRecord understands a range
      search[:started] = from..to
    end

    Cyclid.logger.debug "search=#{search.inspect}"

    # Find the number of matching jobs
    count = if search.empty?
              org.job_records.count
            else
              org.job_records
                 .where(search)
                 .count
            end

    Cyclid.logger.debug "count=#{count}"

    stats_only = params[:stats_only] || false
    limit = (params[:limit] || 100).to_i
    offset = (params[:offset] || 0).to_i

    job_data = { 'total' => count,
                 'offset' => offset,
                 'limit' => limit }

    unless stats_only
      # Get the available job records, but be terse with the
      # information returned; there is no need to return a full job log
      # with every job, for example.
      job_records = if search.empty?
                      org.job_records
                         .all
                         .select('id, job_name, job_version, started, ended, status')
                         .offset(offset)
                         .limit(limit)
                    else
                      org.job_records
                         .where(search)
                         .select('id, job_name, job_version, started, ended, status')
                         .offset(offset)
                         .limit(limit)
                    end

      job_data['records'] = job_records
    end

    return job_data.to_json
  end

  # Create and run a job.
  app.post do
    authorized_for!(params[:name], Operations::WRITE)

    payload = parse_request_body
    Cyclid.logger.debug payload

    halt_with_json_response(400, INVALID_JOB, 'invalid job definition') \
      unless payload.key? 'sequence' and \
             payload.key? 'environment'

    begin
      job_id = job_from_definition(payload)
    rescue StandardError => ex
      halt_with_json_response(500, INVALID_JOB, "job failed: #{ex}")
    end

    return { job_id: job_id }.to_json
  end

  # Get the complete JobRecord for the given job ID.
  app.get '/:id' do
    authorized_for!(params[:name], Operations::READ)

    org = Organization.find_by(name: params[:name])
    halt_with_json_response(404, INVALID_ORG, 'organization does not exist') \
      if org.nil?

    begin
      job_record = org.job_records.find(params[:id])
      halt_with_json_response(404, INVALID_JOB, 'job does not exist') \
        if job_record.nil?
    rescue StandardError
      halt_with_json_response(404, INVALID_JOB, 'job does not exist')
    end

    job = job_record.serializable_hash
    job[:job_id] = job.delete :id

    # XXX The "job" itself is a serialised internal representation and
    # probably not very useful to the user, so we might want to process
    # it into something more helpful here.
    return job.to_json
  end

  # Get the current status of the given job ID.
  app.get '/:id/status' do
    authorized_for!(params[:name], Operations::READ)

    org = Organization.find_by(name: params[:name])
    halt_with_json_response(404, INVALID_ORG, 'organization does not exist') \
      if org.nil?

    job_record = org.job_records.find(params[:id])
    halt_with_json_response(404, INVALID_JOB, 'job does not exist') \
      if job_record.nil?

    hash = {}
    hash[:job_id] = job_record.id
    hash[:status] = job_record.status
    hash[:started] = job_record.started if job_record.started
    hash[:ended] = job_record.ended if job_record.ended

    return hash.to_json
  end

  # Get the current complete log of the given job ID.
  app.get '/:id/log' do
    authorized_for!(params[:name], Operations::READ)

    org = Organization.find_by(name: params[:name])
    halt_with_json_response(404, INVALID_ORG, 'organization does not exist') \
      if org.nil?

    job_record = org.job_records.find(params[:id])
    halt_with_json_response(404, INVALID_JOB, 'job does not exist') \
      if job_record.nil?

    hash = {}
    hash[:job_id] = job_record.id
    hash[:log] = job_record.log

    return hash.to_json
  end

  app.helpers do
    include Job::Helpers
  end
end

Instance Method Details

#GET(/organizations/: organization/jobs/:job) ⇒ Object

Get the complete JobRecord for the given job ID.

Parameters:

  • organization (String)

    Name of the organization.

  • job (Integer)

    Job ID.

Returns:

  • The job record for the job ID.

  • (404)

    The organization or job record does not exist.



# File 'app/cyclid/controllers/organizations/job.rb', line 73

#GET(/organizations/: organization/jobs/:job/log) ⇒ Object

Get the current complete log of the given job ID.

Parameters:

  • organization (String)

    Name of the organization.

  • job (Integer)

    Job ID.

Returns:

  • The job log for the job ID.

  • (404)

    The organization or job record does not exist.



# File 'app/cyclid/controllers/organizations/job.rb', line 91

#GET(/organizations/: organization/jobs/:job/status) ⇒ Object

Get the current status of the given job ID.

Parameters:

  • organization (String)

    Name of the organization.

  • job (Integer)

    Job ID.

Returns:

  • The current job status for the job ID.

  • (404)

    The organization or job record does not exist.



# File 'app/cyclid/controllers/organizations/job.rb', line 82

#GET(/organizations/: organization/jobs) ⇒ Object

Get a list of jobs that have been run for the organization. Jobs can be filtered using the s_name, s_status, s_from and s_to search parameters. If s_from & s_to are given, only jobs which started between the two times will be returned.

Parameters:

  • organization (String)

    Name of the organization.

  • stats_only (Boolean)

    Do not return the job records; just the count

  • limit (Integer)

    Maxiumum number of records to return.

  • offset (Integer)

    Offset to start returning records.

  • s_name (String)

    Name of the job to search on.

  • s_status (Integer)

    Status to search on.

  • s_from (String)

    Date & time to search from.

  • s_to (String)

    Date & time to search to.

Returns:

  • The list of job details.

  • (404)

    The organization does not exist.



# File 'app/cyclid/controllers/organizations/job.rb', line 28

#POST(/organizations/: organization/jobs) ⇒ 200, ...

Create and run a job. The job definition can be either a JSON or YAML document.

Examples:

Create a simple job in the ‘example’ organization with no secrets or ad-hoc stages

POST /organizations/example/jobs <= {"name": "example",
                                     "environment" : {
                                       "os" : "ubuntu_trusty"
                                      },
                                      "sequence": [
                                        {
                                          "stage": "example_stage"
                                        }
                                      ]}

Parameters:

  • organization (String)

    Name of the organization.

  • body (JSON)

    Job definition

Options Hash (body):

  • name (String)

    Name of the job.

  • environment (Object)

    Job runtime environment details. At a minimum this must include the operating system name & version to use.

  • secrets (Object) — default: {}

    Encrypted secret data for use by the job.

  • stages (Array<Object>) — default: []

    Ad-hoc stage definitions which are local to this job.

  • sequence (Array<Object>) — default: []

    List of stages to be run.

Returns:

  • (200)

    The job was created and successfully queued.

  • (400)

    The job definition was invalid.

  • (404)

    The organization does not exist.



# File 'app/cyclid/controllers/organizations/job.rb', line 46