-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow use of host:port in a FROM instruction #75
base: master
Are you sure you want to change the base?
Conversation
@lorenzo @m-ildefons , hi can you please take a look when you have some time? |
Hi @petitlapin ,
Let me know if you need any help with that. |
Hi, |
Hi, not sure on how much time you want to spend helping me but if you don't have, I guess we can close this PR and it can be implemented later by someone who has the knowledge. parseRegistry :: (?esc :: Char) => Parser Registry
parseRegistry = do
registry <- someUnless "a domain name" (\c -> c== '/') will give me whatever is before '/' if there is one. |
Hi, Regarding your question, try writing down the type signature of such a function first, it makes things somewhat easier: isDomainName :: Text -> Bool The input is just a isDomainName dom
| isJust (find (== '.') dom) = True
| isJust (find (== ':') dom) = True
| otherwise = False This is Haskell syntax expressing the equivalent of a Just as a side note, You can't call A -- This parser will succeed only if it can find something that looks like a domain name
-- at the beginning of the input. In case it also finds something that looks like a port
-- (e.g. `:5000`) it will also consume that and append it at the end of the return value.
parseRegistry :: Parser Registry
parseRegistry = do
domain <- parseDomain
port <- optional parsePort -- note the `optional` [1]
if isJust port
then return $ Registry ( domain <> ":" <> port )
else return $ Registry domain
-- This parser only succeeds if it can find something that roughly looks like a domain name
parseDomain :: Parser Text
parseDomain = do
subdomain <- someUnless "a subdomain" (/= '.')
void $ char '.' -- this ensures there is at least one dot '.' in the domain (e.g. 'docker.io')
domain <- someUnless "a domain" isIllegalChar
return $ subdomain <> "." <> domain
where
-- returns `False` as long as the given char may occur in a domain name and `True` if it is
-- illegal in the context of a domain name (e.g. ':', '/', '&')
isIllegalChar :: Char -> Bool
isIllegalChar c = (not isAlphaNum c) && (c /= '.')
parsePort :: Parser Text
parsePort = do
void $ char ':' -- needs to start with colon, but we will throw it away
some digitChar -- one or more digits, fails if there are none I haven't tried any of these parser, but I think they should convey how the program could be structured and how combinators can be leveraged to deal with optional parts of a URI. Note however that this is still a very naive implementation and will fail horribly in edge cases like raw IPv6 addresses. [1] The I hope you are not discouraged from Haskell by this. You are working on a hard problem and these parsers are not easy to grok. If you have more questions, feel free to ask, I'm happy to help you. |
Hi, don't worry for the delay, 3-4 days is more than acceptable :). I have a few things to do before coming back to this PR but I'll check it as soon as I can. Thank you again for the complete explanation (and yes, there is no need to do a solution in a hurry if it is not good enough or come back to it later) |
Hi, I still have issues trying to understand how to make it work. A registry can either be (I added the corresponding unit test in the PR): followed by a slash. However, if there are neither a tld or a port, it is not a domain but part of image name. parseRegistry :: Parser Registry
parseRegistry = do
domain <- (Just <$> try parseUntilDotOrSemiColonAndNoSlash) <|> return Nothing -- if we find a / before a : or a ., there is no registry
port <- (Just <$> try parseUntilSlash) <|> return Nothing
return $ Registry (domain <> separator <> port) -- where 'separator' would be the first : or . found so parseUntilDotOrSemiColonAndNoSlash would be something like: parseUntilDotOrSemiColonAndNoSlash :: Parser Text
parseUntilDotOrSemiColonAndNoSlash = do
subdomain <- someUnless "a subdomain" (\c -> c == '.' || c == '/' || c == ':')
if c == '/' -- Issue: how can we access c here or fail above if the first character is a '/'?
then return Nothing
else return $ subdomain and parseUntilSlash: parseUntilSlash :: Parser Text
parseUntilSlash = do
portOrTld <- someUnless "a subdomain" ( == '/')
return $ portOrTld I can commit the (non working) code if it is easier to debug. |
when having a FROM line like:
FROM myregistry:port/imagename:tag
, there is an errorunexpected ':' expecting '@', a new line followed by the next instruction, at least one space, or the image tag
.This patch proposes to simplify how the registry is computed.
fixes: hadolint/hadolint#355
Note: I don't know haskell, I tested the change by cloning the repo, and testing on a local file using the test in integration-tests