-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
added support for tmpfs-mode in compose file #808
Conversation
Codecov Report
@@ Coverage Diff @@
## master #808 +/- ##
==========================================
+ Coverage 50.92% 51.01% +0.08%
==========================================
Files 237 237
Lines 15332 15362 +30
==========================================
+ Hits 7808 7837 +29
- Misses 7024 7025 +1
Partials 500 500 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Design LGTM
design looks good to me as well; moving to code review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Left some comments
@@ -261,6 +261,12 @@ | |||
"properties": { | |||
"nocopy": {"type": "boolean"} | |||
} | |||
}, | |||
"tmpfs": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 3.2 ... 3.5 formats have been released, so those formats are now frozen; to add a new feature to the existing formats, a new version (3.6) needs to be created.
cli/compose/loader/volume.go
Outdated
@@ -15,7 +15,6 @@ const endOfSpec = rune(0) | |||
// ParseVolume parses a volume spec without any knowledge of the target platform | |||
func ParseVolume(spec string) (types.ServiceVolumeConfig, error) { | |||
volume := types.ServiceVolumeConfig{} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you revert this change?
cli/compose/convert/volume.go
Outdated
} | ||
|
||
// Anonymous volumes | ||
if volume.Source == "" && volume.Type != "tmpfs" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this was already in the existing code, but this looks like a bug, as this allows a type=bind
without specifying a source
;
version: "3.5"
services:
tmpfs:
image: nginx:alpine
volumes:
- type: bind
target: /app
I suggest moving this validation into the handleVolumeToMount()
, handleBindToMount()
, and handleTmpfsToMount()
functions; it makes the logic easier to follow, and puts validation with each type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, interesting; it looks like there's actually a different issue as well; if nosource:
is specified, docker stack deploy
resolves this to the directory of the docker-compose.yml
; I think that's not the correct behaviour; if no source is specified, it should produce an error (if you want to use the directory of the docker-compose file, an explicit source: "./"
or source: "."
should be required)
@dnephin @vdemeester ^^ wdyt?
cli/compose/convert/volume.go
Outdated
} | ||
if volume.Tmpfs != nil { | ||
result.TmpfsOptions = &mount.TmpfsOptions{ | ||
SizeBytes: volume.Tmpfs.Size, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need validation of the Size
property itself? (i.e., should likely be a positive integer)
Possibly this can be handled by the JSON-schema (see my other comment), but we should check if that is sufficient
cli/compose/convert/volume.go
Outdated
volume composetypes.ServiceVolumeConfig, | ||
result mount.Mount, | ||
) (mount.Mount, error) { | ||
// source must be empty for tmpfs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is a bit redundant
cli/compose/convert/volume.go
Outdated
stackVolumes volumes, | ||
namespace Namespace, | ||
) (mount.Mount, error) { | ||
result := mount.Mount{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a big fan of moving this outside of the handleXX
functions; I assume you kept it out to reduce code duplication, but now the conversion (and validation) is "split" between the handleXX
functions and this function.
Given that not all mount-types use the same options in this type (e.g., type=bind
uses Source
, but type=tmpfs
doesn't), I'd move this code to each handleXX
function. If duplication of code is a concern (but I think it's minimal), you could have a helper function for the shared code
cli/compose/convert/volume.go
Outdated
Propagation: mount.Propagation(volume.Bind.Propagation), | ||
} | ||
} | ||
// Binds volumes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment doesn't add much, so I'd remove it
cli/compose/convert/volume.go
Outdated
SizeBytes: volume.Tmpfs.Size, | ||
} | ||
} | ||
// Tmpfs volumes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment doesn't add much, so I'd remove it; if the function needs documentation, add a GoDoc for the function itself
"tmpfs": { | ||
"type": "object", | ||
"properties": { | ||
"size": {"type": "number"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be "type": "integer"
?
If only positive integers are allowed, likely:
{
"type": "integer",
"exclusiveMinimum": 0
}
(not sure if exclusiveMinimum
or minimum
; likely depends on how empty values are handled)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the Docker documentation if tmpfs-size isn't provided it will be unlimited by default:
Option | Description |
---|---|
tmpfs-size | Size of the tmpfs mount in bytes. Unlimited by default. |
So if the user wants to specify a ceiling of how many bytes to allocate, then they should provide a positive integer above zero. The docker cli, as it behaves now, will not allow negative numbers:
invalid argument "type=tmpfs,destination=/app,tmpfs-size=-1" for --mount: invalid value for tmpfs-size: -1
It will allow zero, but when you inspect the container it just defaults TmpfsOptions to an empty object, which (since tmpfs-size won't actually be set) will allocate "unlimited" resources:
"Mounts": [
{
"Type": "tmpfs",
"Target": "/app",
"TmpfsOptions": {}
}
]
So I think we should, as you said, use an exclusiveMinimum of zero. That way the user at least attaches the TmpfsOptions with a value above zero for tmpfs-size. I will go ahead and add that to the 3.6v schema, unless someone thinks it should be handled differently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the CLI uses zero as equivalent of "not set", then probably minimum
should be used (zero is a valid value, but indicates "no limit").
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I will Git started on those changes
@@ -296,6 +296,11 @@ type ServiceVolumeVolume struct { | |||
NoCopy bool `mapstructure:"nocopy"` | |||
} | |||
|
|||
// ServiceVolumeTmpfs are options for a service volume of type tmpfs | |||
type ServiceVolumeTmpfs struct { | |||
Size int64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be an uint64
? Or is a signed integer used elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chose to use int64 over unit64 because the mount struct looked to expect TmpfsOptions to contain it. Source:
https://github.com/moby/moby/blob/6415f1dcf5c79da853c604733c56b43ae3d18ced/api/types/mount/mount.go#L108
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Wonder if that was for a reason ("special -1
value, e.g.) or just overlooked during review of the initial implementation. 🤔
Thanks for the helpful feedback. I will make the necessary changes and update the PR. |
I believe that I addressed most of the concerns that @thaJeztah brought up in my latest PR, with the exception being the issue regarding the directory of the compose file being set when a source is not passed to a volume of type bind (using the long compose syntax). I added explicit checks for an empty source in the convert package, but by the time it is received there it is already set. I am happy to alter/fix the behavior in this PR if it is decided that the current functionality is not desired. Or we/I can make a separate issue for it and address it in a different PR. Thanks! 😄 |
Not sure why jenkins didn't run the integration suite. I forced a build from https://jenkins.dockerproject.org/job/docker/job/cli/view/change-requests/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is looking good. Just a couple minor comments.
cli/compose/convert/volume.go
Outdated
) (mount.Mount, error) { | ||
|
||
switch volume.Type { | ||
case "volume": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the old default (when type is not set) would be volume, so I guess this case should also have ""
cli/compose/convert/volume.go
Outdated
if volume.Type == "bind" && volume.Volume != nil { | ||
return result, errors.New("volume options are incompatible with type bind") | ||
if volume.Type != "tmpfs" { | ||
result.Source = volume.Source |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't really necessary because handleTmpfsToMount()
will error out in this case. I would remove this so we don't have to check it in two places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ethan-haynes! Changes in this PR look good to me 🎉
I have one nit left;
Can you squash your commits (we tend to keep changes made following "review comments" out of our git history), but keep separate commits for the compose-file spec changes, so:
- 1 commit that copies the compose 3.5 spec to 3.6 (and updates the
cli/compose/schema/bindata.go
accordingly) - 1 commit that adds the new
"tmpfs"
field to the compose file spec (and updates thecli/compose/schema/bindata.go
accordingly) - 1 commit with your code changes
(You can combine 2. and 3. in a single commit if you prefer)
Doing so makes it easier to see the changes that were made in the new 3.6 spec, and makes it easier to find which commit added the new field in git history.
Signed-off-by: Ethan Haynes <ethanhaynes@alumni.harvard.edu>
Signed-off-by: Ethan Haynes <ethanhaynes@alumni.harvard.edu>
Signed-off-by: Ethan Haynes <ethanhaynes@alumni.harvard.edu>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with squashed commits
747dd8a
to
cd69d08
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perfect! LGTM, thanks so much 👍
ping @shin- for Docker Compose |
Oh! before I forget; @ethan-haynes could you also take care of updating the compose-file documentation? Possibly needs to go in the |
Yes, that's correct if it applies to a not-yet-released feature of Compose. |
Sounds good. I'll go ahead and update the documentation with new examples for the 3.6v compose release. 📝 |
Provides a fix for #698
- What I did
Added the ability to use a tmpfs volume type in compose with the optional parameter of size.
- How I did it
Changed compose schemas 3.2-3.5 to allow for the type. Tweaked volumes parser to read it.
Removed it from unapproved params.
- How to verify it
Test it with compose: