extern crate dockerfile_parser;
use dockerfile_parser::*;
use indoc::indoc;
use pretty_assertions::assert_eq;
#[test]
fn parse_basic() -> Result<(), dockerfile_parser::Error> {
let dockerfile = Dockerfile::parse(
r#"
FROM alpine:3.10
RUN apk add --no-cache curl
"#,
)?;
assert_eq!(dockerfile.instructions.len(), 2);
assert_eq!(
dockerfile.instructions[0],
Instruction::From(FromInstruction {
span: Span { start: 5, end: 21 },
image: SpannedString {
span: Span { start: 10, end: 21 },
content: "alpine:3.10".into(),
},
image_parsed: ImageRef {
registry: None,
image: "alpine".into(),
tag: Some("3.10".into()),
hash: None
},
index: 0,
alias: None,
flags: vec![],
})
);
assert_eq!(
&dockerfile.instructions[1]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"apk add --no-cache curl"
);
Ok(())
}
#[test]
fn parse_multiline_shell() -> Result<(), dockerfile_parser::Error> {
let dockerfile = Dockerfile::parse(indoc!(
r#"
RUN apk add --no-cache \
curl
RUN foo
"#
))?;
assert_eq!(dockerfile.instructions.len(), 2);
assert_eq!(
&dockerfile.instructions[0]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"apk add --no-cache curl"
);
assert_eq!(
&dockerfile.instructions[1]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"foo"
);
Ok(())
}
#[test]
fn parse_multiline_exec() -> Result<(), dockerfile_parser::Error> {
let dockerfile = Dockerfile::parse(
r#"
RUN ["apk", \
"add", \
"--no-cache", \
"curl"]
RUN foo
"#,
)?;
assert_eq!(dockerfile.instructions.len(), 2);
assert_eq!(
dockerfile.instructions[0]
.as_run()
.unwrap()
.as_exec()
.unwrap()
.as_str_vec(),
&["apk", "add", "--no-cache", "curl"]
);
assert_eq!(
&dockerfile.instructions[1]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"foo"
);
Ok(())
}
#[test]
fn parse_label() -> Result<(), dockerfile_parser::Error> {
let dockerfile = Dockerfile::parse(
r#"
LABEL foo=bar
LABEL "foo"="bar"
LABEL "foo=bar"=bar
LABEL foo="bar\
baz"
RUN foo
"#,
)?;
assert_eq!(dockerfile.instructions.len(), 5);
assert_eq!(
dockerfile.instructions[0].as_label().unwrap(),
&LabelInstruction {
span: Span::new(5, 18),
labels: vec![Label::new(
Span::new(11, 18),
SpannedString {
span: Span::new(11, 14),
content: "foo".to_string(),
},
SpannedString {
span: Span::new(15, 18),
content: "bar".to_string(),
},
)]
}
);
assert_eq!(
dockerfile.instructions[1],
Instruction::Label(LabelInstruction {
span: Span::new(24, 41),
labels: vec![Label::new(
Span::new(30, 41),
SpannedString {
span: Span::new(30, 35),
content: "foo".to_string(),
},
SpannedString {
span: Span::new(36, 41),
content: "bar".to_string(),
},
)]
})
);
assert_eq!(
dockerfile.instructions[2],
Instruction::Label(LabelInstruction {
span: Span::new(47, 66),
labels: vec![Label::new(
Span::new(53, 66),
SpannedString {
span: Span::new(53, 62),
content: "foo=bar".to_string(),
},
SpannedString {
span: Span::new(63, 66),
content: "bar".to_string(),
},
)]
})
);
assert_eq!(
dockerfile.instructions[3],
Instruction::Label(LabelInstruction {
span: Span::new(72, 102),
labels: vec![Label::new(
Span::new(78, 102),
SpannedString {
span: Span::new(78, 81),
content: "foo".to_string(),
},
SpannedString {
span: Span::new(82, 102),
content: "bar baz".to_string(),
},
)]
})
);
assert_eq!(
&dockerfile.instructions[4]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"foo"
);
assert!(Dockerfile::parse(
r#"
LABEL foo="bar\
baz"\
RUN foo
"#
)
.is_err());
Ok(())
}
#[test]
fn parse_comment() -> Result<(), dockerfile_parser::Error> {
let dockerfile = Dockerfile::parse(
r#"
# lorem ipsum
LABEL foo=bar
#dolor sit amet
# consectetur adipiscing elit
# sed do eiusmod
# Duis aute irure dolor
# tempor incididunt ut labore
LABEL "foo"="bar"
# et dolore magna aliqua
LABEL "foo=bar"=bar
#Ut enim ad minim veniam
LABEL foo="bar\
baz"
# quis nostrud exercitation
# ullamco laboris nisi
RUN foo
ENV foo=a \
# test comment
bar=b
run [ \
"echo", \
# hello world
"hello", \
"world" \
]
run echo 'hello # world'
"#,
)?;
assert_eq!(dockerfile.instructions.len(), 8);
assert_eq!(
&dockerfile.instructions[4]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"foo"
);
assert_eq!(
dockerfile.instructions[5].as_env().unwrap().vars,
vec![
EnvVar::new(
Span::new(396, 401),
SpannedString {
span: Span::new(396, 399),
content: "foo".to_string(),
},
((400, 401), "a")
),
EnvVar::new(
Span::new(433, 438),
SpannedString {
span: Span::new(433, 436),
content: "bar".to_string(),
},
((437, 438), "b")
),
]
);
assert_eq!(
dockerfile.instructions[6]
.as_run()
.unwrap()
.as_exec()
.unwrap()
.as_str_vec(),
vec!["echo", "hello", "world"]
);
assert_eq!(
dockerfile.instructions[7]
.as_run()
.unwrap()
.as_shell()
.unwrap()
.to_string(),
"echo 'hello # world'"
);
Ok(())
}
#[test]
fn parse_from_sha256_digest() -> Result<(), dockerfile_parser::Error> {
let dockerfile = Dockerfile::parse(
r#"
FROM alpine@sha256:074d3636ebda6dd446d0d00304c4454f468237fdacf08fb0eeac90bdbfa1bac7 as foo
"#,
)?;
assert_eq!(dockerfile.instructions.len(), 1);
assert_eq!(
dockerfile.instructions[0].as_from(),
Some(&FromInstruction {
index: 0,
span: (5, 95).into(),
image: SpannedString {
span: Span { start: 10, end: 88 },
content:
"alpine@sha256:074d3636ebda6dd446d0d00304c4454f468237fdacf08fb0eeac90bdbfa1bac7"
.into(),
},
image_parsed: ImageRef {
registry: None,
image: "alpine".into(),
tag: None,
hash: Some(
"sha256:074d3636ebda6dd446d0d00304c4454f468237fdacf08fb0eeac90bdbfa1bac7"
.into()
),
},
alias: Some(SpannedString {
span: Span { start: 92, end: 95 },
content: "foo".into(),
}),
flags: vec![],
})
);
Ok(())
}