language-docker 10.3.0 → 10.4.0
raw patch · 4 files changed
+208/−20 lines, 4 files
Files
- language-docker.cabal +2/−2
- src/Language/Docker/Parser/Prelude.hs +28/−3
- src/Language/Docker/Parser/Run.hs +39/−6
- test/Language/Docker/ParseRunSpec.hs +139/−9
language-docker.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: e958774001a0ee7648ae873f3676eeb96096d835bfc0ce02bf292d23c4f1b716+-- hash: 309a0c933f6e5edbdfbe096391f0b79e6a6f9218347d912f390d58a9c7c7c475 name: language-docker-version: 10.3.0+version: 10.4.0 synopsis: Dockerfile parser, pretty-printer and embedded DSL description: All functions for parsing and pretty-printing Dockerfiles are exported through @Language.Docker@. For more fine-grained operations look for specific modules that implement a certain functionality. See the <https://github.com/hadolint/language-docker GitHub project> for the source-code and examples.
src/Language/Docker/Parser/Prelude.hs view
@@ -35,6 +35,7 @@ char, L.charLiteral, string,+ string', void, when, Text,@@ -173,11 +174,35 @@ heredocContent :: Text -> Parser Text heredocContent marker = do- foo <- observing $ string $ marker <> "\n"- doc <- case foo of- Left _ -> manyTill anySingle (string $ "\n" <> marker <> "\n")+ emptyHeredoc <- observing delimiter+ doc <- case emptyHeredoc of+ Left _ -> manyTill anySingle termination Right _ -> pure "" return $ T.strip $ T.pack doc+ where+ termination :: Parser Text+ termination = try terEOL <|> terEOF++ terEOL :: Parser Text+ terEOL = string $ "\n" <> marker <> "\n"++ terEOF :: Parser Text+ terEOF = do+ t <- string $ "\n" <> marker+ hidden eof+ pure t++ delimiter :: Parser Text+ delimiter = try delEOL <|> delEOF++ delEOL :: Parser Text+ delEOL = string $ marker <> "\n"++ delEOF :: Parser Text+ delEOF = do+ t <- string marker+ hidden eof+ pure t heredoc :: Parser Text heredoc = do
src/Language/Docker/Parser/Run.hs view
@@ -202,15 +202,13 @@ [ mountArgTarget, mountArgSource, mountArgFromImage,- mountArgReadOnly,- mountArgReadWrite+ mountArgReadOnly ] Cache -> [ mountArgTarget, mountArgSource, mountArgFromImage, mountArgReadOnly,- mountArgReadWrite, mountArgId, mountArgSharing, mountArgMode,@@ -234,6 +232,9 @@ key :: Text -> Parser a -> Parser a key name p = string (name <> "=") *> p +tryKeyValue' :: Text -> Text -> Parser Text+tryKeyValue' k v = try $ string' (k <> "=") *> string' v+ cacheSharing :: Parser CacheSharing cacheSharing = choice [Private <$ string "private", Shared <$ string "shared", Locked <$ string "locked"]@@ -251,10 +252,42 @@ mountArgMode = MountArgMode <$> key "mode" stringArg mountArgReadOnly :: Parser RunMountArg-mountArgReadOnly = MountArgReadOnly <$> (choice ["ro", "readonly"] $> True)+mountArgReadOnly =+ MountArgReadOnly+ <$> choice+ [ choiceRoExplicit,+ choiceRwExplicit,+ choiceRo, -- these two must come last and be separate+ choiceRw+ ]+ where+ choiceRoExplicit =+ choice+ [ tryKeyValue' "ro" "true",+ tryKeyValue' "rw" "false",+ tryKeyValue' "readonly" "true",+ tryKeyValue' "readwrite" "false"+ ] $> True -mountArgReadWrite :: Parser RunMountArg-mountArgReadWrite = MountArgReadOnly <$> (choice ["rw", "readwrite"] $> False)+ choiceRwExplicit =+ choice+ [ tryKeyValue' "rw" "true",+ tryKeyValue' "ro" "false",+ tryKeyValue' "readwrite" "true",+ tryKeyValue' "readonly" "false"+ ] $> False++ choiceRo =+ choice+ [ string' "ro",+ string' "readonly"+ ] $> True++ choiceRw =+ choice+ [ string' "rw",+ string' "readwrite"+ ] $> False mountArgRequired :: Parser RunMountArg mountArgRequired = MountArgRequired <$> choice
test/Language/Docker/ParseRunSpec.hs view
@@ -330,37 +330,159 @@ [ Run $ RunArgs (ArgumentsText "echo foo") flags ] + describe "RUN with --mount flag and different ways to write ro/rw" $ do+ let flagsRo = def { mount = Set.singleton $+ BindMount+ ( def+ { bTarget = "/foo",+ bSource = Just "/bar",+ bReadOnly = Just True+ }+ )+ }+ flagsRw = def { mount = Set.singleton $+ BindMount+ ( def+ { bTarget = "/foo",+ bSource = Just "/bar",+ bReadOnly = Just False+ }+ )+ }+ in do+ it "--mount=type=bind,ro" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,ro echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,RO" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,RO echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,readonly" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readonly echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,Readonly" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,Readonly echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,ro=true" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,ro=true echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,RO=TRUE" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,RO=TRUE echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,readonly=true" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readonly=true echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,Readonly=True" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,Readonly=True echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,ro=True" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,ro=True echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,readonly=True" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readonly=True echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,rw=false" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,rw=false echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,readwrite=false" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readwrite=false echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,rw=False" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,rw=False echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]+ it "--mount=type=bind,readwrite=False" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readwrite=False echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRo ]++ it "--mount=type=bind,rw" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,rw echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,readwrite" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readwrite echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,rw=true" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,rw=true echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,readwrite=true" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readwrite=true echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,rw=True" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,rw=True echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,readwrite=True" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readwrite=True echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,ro=false" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,ro=false echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,readonly=false" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readonly=false echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,ro=False" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,ro=False echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ it "--mount=type=bind,readonly=False" $+ let file = Text.unlines+ [ "RUN --mount=type=bind,target=/foo,source=/bar,readonly=False echo foo" ]+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo foo") flagsRw ]+ describe "parse RUN in heredocs format" $ do it "foo heredoc" $- let file = Text.unlines [ "RUN <<EOF", "foo", "EOF"]+ let file = Text.unlines [ "RUN <<EOF", "foo", "EOF" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ]+ it "foo heredoc without newline at end" $+ let file = "RUN <<EOF\nfoo\nEOF"+ flags = def { security = Nothing }+ in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "foo heredoc marker" $- let file = Text.unlines [ "RUN <<FOO", "foo", "FOO"]+ let file = Text.unlines [ "RUN <<FOO", "foo", "FOO" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "foo heredoc quoted marker" $- let file = Text.unlines [ "RUN <<\"FOO\"", "foo", "FOO"]+ let file = Text.unlines [ "RUN <<\"FOO\"", "foo", "FOO" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "foo heredoc single quoted marker" $- let file = Text.unlines [ "RUN <<\'FOO\'", "foo", "FOO"]+ let file = Text.unlines [ "RUN <<\'FOO\'", "foo", "FOO" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "foo heredoc +dash" $- let file = Text.unlines [ "RUN <<-FOO", "foo", "FOO"]+ let file = Text.unlines [ "RUN <<-FOO", "foo", "FOO" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "foo heredoc quoted +dash" $- let file = Text.unlines [ "RUN <<-\"FOO\"", "foo", "FOO"]+ let file = Text.unlines [ "RUN <<-\"FOO\"", "foo", "FOO" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "foo heredoc single quoted +dash" $- let file = Text.unlines [ "RUN <<-\'FOO\'", "foo", "FOO"]+ let file = Text.unlines [ "RUN <<-\'FOO\'", "foo", "FOO" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo") flags ] it "multiline foo heredoc" $- let file = Text.unlines [ "RUN <<EOF", "foo", "bar", "", "dodo", "EOF"]+ let file = Text.unlines [ "RUN <<EOF", "foo", "bar", "", "dodo", "EOF" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "foo\nbar\n\ndodo") flags ] it "heredoc with shebang/commend" $@@ -368,9 +490,13 @@ flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "#/usr/bin/env python\n\n#print foo\nprint(\"foo\")") flags ] it "empty heredoc" $- let file = Text.unlines [ "RUN <<EOF", "EOF"]+ let file = Text.unlines [ "RUN <<EOF", "EOF" ] flags = def { security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "") flags ]+ it "empty heredoc not followed by newline" $+ let file = "RUN <<EOF\nEOF"+ flags = def { security = Nothing }+ in assertAst file [ Run $ RunArgs (ArgumentsText "") flags ] it "evil heredoc" $ let file = Text.unlines [ "RUN <<EOF foo", "bar EOF", "EOF"] flags = def { security = Nothing }@@ -400,5 +526,9 @@ ] it "heredoc correct termination" $ let file = Text.unlines [ "RUN <<EOF", "echo $EOF", "EOF" ]+ flags = def {security = Nothing }+ in assertAst file [ Run $ RunArgs (ArgumentsText "echo $EOF") flags ]+ it "heredoc correct termination without newline" $+ let file = "RUN <<EOF\necho $EOF\nEOF" flags = def {security = Nothing } in assertAst file [ Run $ RunArgs (ArgumentsText "echo $EOF") flags ]