Class: Kennel::ValidatePlan::DashboardValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/kennel/tasks/validate_plan.rb

Constant Summary collapse

COSMETIC_FIELDS =
["title", "description", "tags"].freeze

Instance Method Summary collapse

Constructor Details

#initialize(item) ⇒ DashboardValidator

Returns a new instance of DashboardValidator.



27
28
29
# File 'lib/kennel/tasks/validate_plan.rb', line 27

def initialize(item)
  @item = item
end

Instance Method Details

#validate(api) ⇒ Object

datadog does not offer a validation api for dashboards, so we insert an invalid widget at the end and see if that is the invalid widget it complains about this will break if they ever start from the back or return errors for everything that is invalid

we do not need to worry about unresolved ids because:

  • alert_graph widgets allows kennel style ids

  • slo widgets allow kennel style ids

  • uptime widgets allow kennel style ids



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/kennel/tasks/validate_plan.rb', line 39

def validate(api)
  json = @item.expected.as_json
  json = Marshal.load(Marshal.dump(json))

  # add a semi-valid (does not fail immediately on missing definition) widget still blocks the request
  placeholder = "invalid_metric_do_not_update"
  json.fetch(:widgets) << {
    definition: {
      type: "timeseries", requests: [{
        response_format: "timeseries",
        queries: [{ data_source: "metrics", name: "restarts", query: placeholder }]
      }]
    },
    layout: { x: 0, y: 0, height: 0, width: 0 } # needed for `layout_type: free` and valid for all
  }

  begin
    if @item.class::TYPE == :update
      api.update("dashboard", @item.actual.fetch(:id), json)
    else
      api.create("dashboard", json)
    end
    raise "Dashboard validation should have failed, live dashboard was update/created by accident"
  rescue StandardError => e
    # parse the JSON in the error message and see if there is anything except our error
    raise "Unreadable error format: #{e.message}" unless (json = e.message[/^\{"errors":.*}$/m])
    data =
      begin
        JSON.parse(json)
      rescue JSON::ParserError
        raise "Unreadable error format: #{json}"
      end
    raise "Unreadable error format: #{data}" unless (errors = data["errors"]) # uncovered
    return if errors.size == 1 && errors.all? { |m| m.include?("unable to parse #{placeholder}") }
    "#{@item.tracking_id}: #{e.message}"
  end
end