Skip to content
This repository has been archived by the owner on Jul 24, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1073 from joyent/ether/v3.1.1-more-fixes
Browse files Browse the repository at this point in the history
v3.1.1 more fixes
  • Loading branch information
karenetheridge authored Dec 8, 2020
2 parents ede58be + 105035d commit 1bfcdb1
Show file tree
Hide file tree
Showing 18 changed files with 102 additions and 43 deletions.
2 changes: 1 addition & 1 deletion cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ requires 'Email::Sender::Simple';
requires 'Email::Sender::Transport::SMTP';
requires 'Net::DNS'; # not used directly, but Email::Valid sometimes demands it
requires 'experimental', '0.020';
requires 'JSON::Schema::Draft201909', '0.017';
requires 'JSON::Schema::Draft201909', '0.019';
requires 'Email::Address::XS', '1.01';
requires 'YAML::PP';
requires 'next::XS';
Expand Down
39 changes: 20 additions & 19 deletions cpanfile.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -2283,22 +2283,22 @@ DISTRIBUTIONS
JSON::PP 2.27300
Scalar::Util 0
perl 5.006
JSON-Schema-Draft201909-0.017
pathname: E/ET/ETHER/JSON-Schema-Draft201909-0.017.tar.gz
provides:
JSON::Schema::Draft201909 0.017
JSON::Schema::Draft201909::Annotation 0.017
JSON::Schema::Draft201909::Document 0.017
JSON::Schema::Draft201909::Error 0.017
JSON::Schema::Draft201909::Result 0.017
JSON::Schema::Draft201909::Utilities 0.017
JSON::Schema::Draft201909::Vocabulary 0.017
JSON::Schema::Draft201909::Vocabulary::Applicator 0.017
JSON::Schema::Draft201909::Vocabulary::Content 0.017
JSON::Schema::Draft201909::Vocabulary::Core 0.017
JSON::Schema::Draft201909::Vocabulary::Format 0.017
JSON::Schema::Draft201909::Vocabulary::MetaData 0.017
JSON::Schema::Draft201909::Vocabulary::Validation 0.017
JSON-Schema-Draft201909-0.019
pathname: E/ET/ETHER/JSON-Schema-Draft201909-0.019.tar.gz
provides:
JSON::Schema::Draft201909 0.019
JSON::Schema::Draft201909::Annotation 0.019
JSON::Schema::Draft201909::Document 0.019
JSON::Schema::Draft201909::Error 0.019
JSON::Schema::Draft201909::Result 0.019
JSON::Schema::Draft201909::Utilities 0.019
JSON::Schema::Draft201909::Vocabulary 0.019
JSON::Schema::Draft201909::Vocabulary::Applicator 0.019
JSON::Schema::Draft201909::Vocabulary::Content 0.019
JSON::Schema::Draft201909::Vocabulary::Core 0.019
JSON::Schema::Draft201909::Vocabulary::Format 0.019
JSON::Schema::Draft201909::Vocabulary::MetaData 0.019
JSON::Schema::Draft201909::Vocabulary::Validation 0.019
requirements:
B 0
Carp 0
Expand Down Expand Up @@ -2805,8 +2805,8 @@ DISTRIBUTIONS
Mojolicious 8.50
SQL::Abstract 1.86
perl 5.016
Mojolicious-8.63
pathname: S/SR/SRI/Mojolicious-8.63.tar.gz
Mojolicious-8.67
pathname: S/SR/SRI/Mojolicious-8.67.tar.gz
provides:
Mojo undef
Mojo::Asset undef
Expand Down Expand Up @@ -2875,11 +2875,12 @@ DISTRIBUTIONS
Mojo::UserAgent::Transactor undef
Mojo::Util undef
Mojo::WebSocket undef
Mojolicious 8.63
Mojolicious 8.67
Mojolicious::Command undef
Mojolicious::Command::Author::cpanify undef
Mojolicious::Command::Author::generate undef
Mojolicious::Command::Author::generate::app undef
Mojolicious::Command::Author::generate::dockerfile undef
Mojolicious::Command::Author::generate::lite_app undef
Mojolicious::Command::Author::generate::makefile undef
Mojolicious::Command::Author::generate::plugin undef
Expand Down
7 changes: 7 additions & 0 deletions docs/json-schema/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@
},
"type" : "object"
},
"date-time" : {
"format" : "date-time",
"not" : {
"pattern" : "^000[01]",
"type" : "string"
}
},
"device_asset_tag" : {
"pattern" : "^\\S+$",
"type" : "string"
Expand Down
6 changes: 3 additions & 3 deletions docs/json-schema/request.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"$ref" : "common.json#/$defs/mojo_standard_placeholder"
},
"started" : {
"format" : "date-time",
"$ref" : "common.json#/$defs/date-time",
"type" : "string"
}
},
Expand Down Expand Up @@ -154,7 +154,7 @@
"minProperties" : 1,
"properties" : {
"completed" : {
"format" : "date-time",
"$ref" : "common.json#/$defs/date-time",
"type" : [
"null",
"string"
Expand All @@ -177,7 +177,7 @@
"$ref" : "common.json#/$defs/mojo_standard_placeholder"
},
"started" : {
"format" : "date-time",
"$ref" : "common.json#/$defs/date-time",
"type" : [
"null",
"string"
Expand Down
4 changes: 4 additions & 0 deletions docs/modules/Conch.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ Stores a [Conch::Time](../modules/Conch%3A%3ATime) instance representing the tim
Retrieves the ["host" in Mojo::URL](https://metacpan.org/pod/Mojo%3A%3AURL#host) portion of the request URL, suitable for constructing base URLs
in user-facing content.

### banner

Banner text suitable for displaying on startup.

## LICENSING

Copyright Joyent, Inc.
Expand Down
1 change: 1 addition & 0 deletions docs/modules/Conch::Route::Build.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Supports the following optional query parameters:
#### `DELETE /build/:build_id_or_name/links`

- Requires system admin authorization or the admin role on the build
- Controller/Action: ["remove\_links" in Conch::Controller::Build](../modules/Conch%3A%3AController%3A%3ABuild#remove_links)
- Request: [request.json#/$defs/BuildLinksOrNull](../json-schema/request.json#/$defs/BuildLinksOrNull)
- Response: `204 No Content`, plus Location header

Expand Down
1 change: 1 addition & 0 deletions docs/modules/Conch::Route::Rack.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ only the rack's phase, or all the rack's devices' phases as well.
#### `DELETE /rack/:rack_id_or_name/links`

- User requires the read/write role on the rack
- Controller/Action: ["remove\_links" in Conch::Controller::Rack](../modules/Conch%3A%3AController%3A%3ARack#remove_links)
- Request: [request.json#/$defs/RackLinksOrNull](../json-schema/request.json#/$defs/RackLinksOrNull)
- Response: `204 No Content`, plus Location header

Expand Down
5 changes: 5 additions & 0 deletions json-schema/common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ $defs:
oneOf:
- format: ipv4
- format: ipv6
date-time:
format: date-time
not:
type: string
pattern: '^000[01]'
macaddr:
type: string
pattern: '^[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}$'
Expand Down
6 changes: 3 additions & 3 deletions json-schema/request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ $defs:
$ref: common.yaml#/$defs/non_empty_string
started:
type: string
format: date-time
$ref: common.yaml#/$defs/date-time
admins:
type: array
uniqueItems: true
Expand All @@ -628,10 +628,10 @@ $defs:
- $ref: common.yaml#/$defs/non_empty_string
started:
type: [ 'null', string ]
format: date-time
$ref: common.yaml#/$defs/date-time
completed:
type: [ 'null', string ]
format: date-time
$ref: common.yaml#/$defs/date-time
links:
$ref: common.yaml#/$defs/links
BuildLinks:
Expand Down
23 changes: 23 additions & 0 deletions lib/Conch.pm
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,29 @@ in user-facing content.
Conch::Route->all_routes($self->routes, $self);

$self->log->info('Conch initialized at '.$self->version_tag);

=head2 banner
Banner text suitable for displaying on startup.
=cut

$self->helper(banner => sub ($c) {
my $banner = <<'BANNER';
/\ _
{-.} ___ ___ _ __ ___| |__
/'-._; / __/ _ \| '_ \ / __| '_ \
_{._ } | (_| (_) | | | | (__| | | |
,' \ `-./ \___\___/|_| |_|\___|_| |_|
\ | /
\, | / Version: %s
\_|/ Started: %s
BANNER

return sprintf($banner, $c->version_tag, $c->startup_time);
});
}

1;
Expand Down
15 changes: 11 additions & 4 deletions lib/Conch/Plugin/JSONValidator.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package Conch::Plugin::JSONValidator;
use Mojo::Base 'Mojolicious::Plugin', -signatures;

use feature 'unicode_strings';
use JSON::Schema::Draft201909 '0.017';
use JSON::Schema::Draft201909 '0.019';
use YAML::PP;
use Mojo::JSON 'to_json';
use Path::Tiny;
use List::Util qw(any none first);
use Try::Tiny;

=pod
Expand Down Expand Up @@ -70,7 +71,7 @@ Returns a boolean.

$app->helper(validate_query_params => sub ($c, $schema_name, $data = $c->req->query_params->to_hash) {
my $validator = $c->json_schema_validator;
my $result = $validator->evaluate($data, 'query_params.yaml#/$defs/'.$schema_name);
my $result = $validator->evaluate($data, 'query_params.yaml#/$defs/'.$schema_name, { collect_annotations => 1 });
if (not $result) {
my @errors = $c->normalize_evaluation_result($result);
$c->log->warn("FAILED query_params validation for schema $schema_name: ".to_json(\@errors));
Expand Down Expand Up @@ -138,13 +139,19 @@ Returns a L<JSON::Schema::Draft201909> object with all JSON Schemas pre-loaded.
$_validator = JSON::Schema::Draft201909->new(
output_format => 'terse',
validate_formats => 1,
collect_annotations => 1,
);
# TODO: blocked on https://github.com/ingydotnet/yaml-libyaml-pm/issues/68
# local $YAML::XS::Boolean = 'JSON::PP'; ... YAML::XS::LoadFile(...)
my $yaml = YAML::PP->new(boolean => 'JSON::PP');
$_validator->add_schema($_, $yaml->load_file('json-schema/'.$_))
try {
$_validator->add_schema($_, $yaml->load_file('json-schema/'.$_))
foreach map path($_)->basename, glob('json-schema/*.yaml');
}
catch {
require Data::Dumper;
die "problems adding schema (YAML is not parseable?) - ",
Data::Dumper->new([ $@->TO_JSON ])->Indent(0)->Terse(1)->Dump;
};

$_validator;
});
Expand Down
2 changes: 2 additions & 0 deletions lib/Conch/Route/Build.pm
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ Supports the following optional query parameters:
=item * Requires system admin authorization or the admin role on the build
=item * Controller/Action: L<Conch::Controller::Build/remove_links>
=item * Request: F<request.yaml#/$defs/BuildLinksOrNull>
=item * Response: C<204 No Content>, plus Location header
Expand Down
2 changes: 2 additions & 0 deletions lib/Conch/Route/Rack.pm
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ only the rack's phase, or all the rack's devices' phases as well.
=item * User requires the read/write role on the rack
=item * Controller/Action: L<Conch::Controller::Rack/remove_links>
=item * Request: F<request.yaml#/$defs/RackLinksOrNull>
=item * Response: C<204 No Content>, plus Location header
Expand Down
5 changes: 3 additions & 2 deletions misc/pod2githubpages
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use Pod::Markdown::Github;
use Class::Method::Modifiers 'around';
use Path::Tiny;
use JSON::MaybeXS;
use YAML::XS;
use YAML::PP;
use List::Util 'any';

my %opts = (
Expand Down Expand Up @@ -144,9 +144,10 @@ foreach my $infile (@all_files) {
path($outfile)->spew($markdown);
}

my $yaml_decoder = YAML::PP->new(boolean => 'JSON::PP');
my $json_encoder = JSON()->new->pretty->indent_length(2)->canonical(1);
foreach my $filename (grep m{^json-schema/[^.]+\.yaml$}, @all_files) {
my $data = YAML::XS::LoadFile($filename);
my $data = $yaml_decoder->load_file($filename);
my $base = path($filename)->basename('.yaml');
my ($type) = $filename =~ m{^json-schema/([^.]+)\.yaml$};
if (any { $type eq $_ } qw(query_params request response common device_report)) {
Expand Down
3 changes: 1 addition & 2 deletions misc/validate
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use warnings;
use open ':std', ':encoding(UTF-8)'; # force stdin, stdout, stderr into utf8

use Getopt::Long;
use JSON::Schema::Draft201909;
use JSON::Schema::Draft201909 0.019;
use Mojo::File 'path';
use JSON::MaybeXS 'decode_json';
use Pod::Usage;
Expand All @@ -25,7 +25,6 @@ pod2usage(1) if $help;
my $js = JSON::Schema::Draft201909->new(
output_format => 'basic',
validate_formats => 1,
collect_annotations => 1,
);

my $schema = $schema_file ? $schema_file : "$schema_url/$name";
Expand Down
11 changes: 8 additions & 3 deletions t/02-json-schemas.t
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use experimental 'signatures';
use Test::More;
use YAML::PP;
use Path::Tiny;
use JSON::Schema::Draft201909;
use Try::Tiny;
use JSON::Schema::Draft201909 0.019;
use JSON::Schema::Draft201909::Utilities 'canonical_schema_uri';

diag 'using JSON::Schema::Draft201909 '.JSON::Schema::Draft201909->VERSION;
Expand All @@ -14,7 +15,6 @@ my $yaml = YAML::PP->new(boolean => 'JSON::PP');
my $js = JSON::Schema::Draft201909->new(
output_format => 'terse',
validate_formats => 1,
collect_annotations => 1,
max_traversal_depth => 67, # needed for other.yaml
);

Expand All @@ -24,7 +24,12 @@ my @files;
foreach my $filename (split /\n/, `git ls-files json-schema`) {
diag('skipping '.$filename), next if $filename =~ /^\./ or $filename !~ /yaml$/;
my $path = path($filename);
$js->add_schema($path->basename, $yaml->load_file($filename));
try {
$js->add_schema($path->basename, $yaml->load_file($filename));
}
catch {
die "$filename is not parseable: ", explain($@->TO_JSON);
};
push @files, $path->basename;
}

Expand Down
1 change: 1 addition & 0 deletions t/conch-rollbar.t
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ package RollbarSimulator {
});
$self->plugin('Conch::Plugin::Features', $self->config);
$self->plugin('Conch::Plugin::JSONValidator', {});
$self->log(Mojo::Log->new(level => 'fatal'));
}
}

Expand Down
12 changes: 6 additions & 6 deletions t/integration/crud/hardware-product.t
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,19 @@ my %hw_fields = (
$t->post_ok('/hardware_product', json => { %hw_fields, specification => 'not json!' } )
->status_is(400)
->json_schema_is('RequestValidationError')
->json_cmp_deeply('/details', superbagof(superhashof({ data_location => '/specification', error => 'wrong type (expected object)' })));
->json_cmp_deeply('/details', [ superhashof({ data_location => '/specification', error => 'wrong type (expected object)' }) ]);

$t->post_ok('/hardware_product', json => { %hw_fields, specification => '{"disk_size":"not an object"}' } )
->status_is(400)
->json_schema_is('RequestValidationError')
->json_cmp_deeply('/details', superbagof(superhashof({ data_location => '/specification', error => 'wrong type (expected object)' })));
->json_cmp_deeply('/details', [ superhashof({ data_location => '/specification', error => 'wrong type (expected object)' }) ]);

$t->post_ok('/hardware_product', json => { %hw_fields, specification => { disk_size => 'not an object' } })
->status_is(400)
->json_schema_is('RequestValidationError')
->json_cmp_deeply({
error => 'request did not match required format',
details => superbagof(superhashof({ data_location => '/specification/disk_size', error => 'wrong type (expected object)' })),
details => [ superhashof({ data_location => '/specification/disk_size', error => 'wrong type (expected object)' }) ],
schema => $base_uri.'json_schema/request/HardwareProductCreate',
});

Expand Down Expand Up @@ -181,19 +181,19 @@ $t->post_ok('/hardware_product', json => {
$t->post_ok("/hardware_product/$new_hw_id", json => { specification => 'not json!' })
->status_is(400)
->json_schema_is('RequestValidationError')
->json_cmp_deeply('/details', superbagof(superhashof({ data_location => '/specification', error => 'wrong type (expected object)' })));
->json_cmp_deeply('/details', [ superhashof({ data_location => '/specification', error => 'wrong type (expected object)' }) ]);

$t->post_ok("/hardware_product/$new_hw_id", json => { specification => '{"disk_size":"not an object"}' })
->status_is(400)
->json_schema_is('RequestValidationError')
->json_cmp_deeply('/details', superbagof(superhashof({ data_location => '/specification', error => 'wrong type (expected object)' })));
->json_cmp_deeply('/details', [ superhashof({ data_location => '/specification', error => 'wrong type (expected object)' }) ]);

$t->post_ok("/hardware_product/$new_hw_id", json => { specification => { disk_size => 'not an object' } })
->status_is(400)
->json_schema_is('RequestValidationError')
->json_cmp_deeply({
error => 'request did not match required format',
details => superbagof(superhashof({ data_location => '/specification/disk_size', error => 'wrong type (expected object)' })),
details => [ superhashof({ data_location => '/specification/disk_size', error => 'wrong type (expected object)' }) ],
schema => $base_uri.'json_schema/request/HardwareProductUpdate',
});

Expand Down

0 comments on commit 1bfcdb1

Please sign in to comment.