1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
#![allow(missing_docs)]
#![cfg_attr(feature="clippy", allow(redundant_closure))]
use serde_yaml;
use std::io::Write;
use std::path::PathBuf;
use valico::json_schema::ValidationState;
error_chain! {
foreign_links {
serde_yaml::Error, Yaml;
}
errors {
ConvertMountedPathToWindows(path: String) {
description("could not converted mounted Docker path to a Windows path")
display("could not convert '{}' to the equivalent Windows path", &path)
}
DoesNotConformToSchema(state: ValidationState) {
description("data did not conform to schema")
display("data did not confirm to schema:{}",
validation_state_to_string(&state))
}
InterpolateInvalidSyntax(s: String) {
description("invalid interpolation syntax")
display("invalid interpolation syntax '{}'", &s)
}
InterpolateUndefinedVariable(s: String) {
description("undefined environment variable in interpolation")
display("undefined environment variable in interpolation '{}'", &s)
}
InterpolationDisabled(s: String) {
description("cannot parse without interpolating environment variables")
display("cannot parse without interpolating environment variables '{}'",
&s)
}
InvalidValue(wanted: String, input: String) {
description("invalid value")
display("invalid {} '{}'", &wanted, &input)
}
ParseEnv(line: String) {
description("cannot parse env variable declaration")
display("cannot parse env variable declaration '{}'", &line)
}
ParseGitUrl(url: String) {
description("not a Docker-compatible git URL")
display("not a Docker-compatible git URL '{}'", &url)
}
ReadFile(path: PathBuf) {
description("error reading file")
display("error reading file '{}'", path.display())
}
UnsupportedVersion(version: String) {
description("unsupported docker-compose.yml version")
display("unsupported docker-compose.yml version '{}'", &version)
}
ValidationFailed {
description("could not validate `docker-compose.yml` file")
display("could not validate `docker-compose.yml` file")
}
WriteFile(path: PathBuf) {
description("error writing to file")
display("error writing to file '{}'", path.display())
}
}
}
impl Error {
pub fn invalid_value<S1, S2>(wanted: S1, input: S2) -> Error
where S1: Into<String>,
S2: Into<String>
{
ErrorKind::InvalidValue(wanted.into(), input.into()).into()
}
}
impl From<ValidationState> for Error {
fn from(state: ValidationState) -> Self {
assert!(!state.is_strictly_valid());
ErrorKind::DoesNotConformToSchema(state).into()
}
}
fn validation_state_to_string(state: &ValidationState) -> String {
let mut out: Vec<u8> = vec![];
for err in &state.errors {
write!(&mut out, "\n- validation error: {:?}", err)
.expect("cannot format validation error");
}
for url in &state.missing {
write!(&mut out, "\n- missing {}", url)
.expect("cannot format URL");
}
String::from_utf8_lossy(&out).into_owned()
}