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
use compose-go to load and parse compose files #4863
base: master
Are you sure you want to change the base?
Conversation
f61e9a4
to
b2467b2
Compare
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #4863 +/- ##
==========================================
- Coverage 61.31% 60.09% -1.23%
==========================================
Files 287 283 -4
Lines 20058 19131 -927
==========================================
- Hits 12298 11496 -802
+ Misses 6867 6782 -85
+ Partials 893 853 -40 |
9d6bf37
to
a696986
Compare
0d2f012
to
6abad62
Compare
You have NO idea how much this improves my job. Merci beaucoup 🫶 |
Silver plates Yeah no this is pretty wonderful if/when it get's accepted. |
21487c5
to
aa63cb7
Compare
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
aa63cb7
to
9705db2
Compare
Go's `net` package [will unlink][1] for us, as long as we used listen to create the Unix socket. Go will even skip the unlink when the socket appears to be abstract (start with a NUL, represented by an @), though we must be cautious to only create sockets with an abstract address on platforms that actually support it -- this caused [several][2] [bugs][3] before. [1]: https://pkg.go.dev/net#UnixListener.SetUnlinkOnClose [2]: docker#4783 [3]: docker#4863 Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
Go's `net` package [will unlink][1] for us, as long as we used Listen & friends to create the Unix socket. Go will even skip the unlink when the socket appears to be abstract (starts with a NUL, represented by an @), though we must be cautious to only create sockets with an abstract address on platforms that actually support it -- this caused [several][2] [bugs][3] before. [1]: https://pkg.go.dev/net#UnixListener.SetUnlinkOnClose [2]: docker#4783 [3]: docker#4863 Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
Go's `net` package [will unlink][1] for us, as long as we used Listen & friends to create the Unix socket. Go will even skip the unlink when the socket appears to be abstract (starts with a NUL, represented by an @), though we must be cautious to only create sockets with an abstract address on platforms that actually support it -- this caused [several][2] [bugs][3] before. [1]: https://pkg.go.dev/net#UnixListener.SetUnlinkOnClose [2]: docker#4783 [3]: docker#4863 Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
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 don't have all the context of the impact these changes will bring but I thought that giving a code review might help push this forward :)
|
||
specLoader "github.com/compose-spec/compose-go/v2/loader" | ||
compose "github.com/compose-spec/compose-go/v2/types" |
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.
nit: keep it consistent with the other import names. Either stick with compose
or composetypes
.
var o []string | ||
|
||
if spec == nil { | ||
return nil, nil |
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.
Although this is an internal function I don't think we should return a nil error and nil value here.
return nil, nil | |
return nil, errors.New("spec is nil") |
for hostName, hostIPs := range extraHosts { | ||
for _, hostIP := range hostIPs { | ||
hosts = append(hosts, hostIP+" "+hostName) | ||
} | ||
} | ||
slices.Sort(hosts) |
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.
"IP-address hostname(s)". The original order of mappings is preserved.
Since this function mentions it keeps the order of hosts, I'm a bit skeptical of this change. Wouldn't sorting the slice here potentially change the original order of the hosts? How do we know if the host mappings were sorted in the first place?
If we do intend to break the original contract, we should then also update the comments on the function to match the new behavior of the function.
r := reflect.ValueOf(service) | ||
for property, value := range types.UnsupportedProperties { | ||
f := reflect.Indirect(r).FieldByName(property) | ||
if f.IsValid() && !f.IsZero() && !slices.Contains(unsupported, value) { | ||
unsupported = append(unsupported, value) |
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 always a bit skeptical of using reflect
. Although the previous solution also seemed quite messy, I'm not sure if this one is better with reflect. A simple if type check might do:
if ok, f := service.(map[string]any); !ok {
return errors.New("not supported")
}
r := reflect.ValueOf(service) | ||
for property, pair := range propertyMap { | ||
f := reflect.Indirect(r).FieldByName(property) | ||
if f.IsValid() && !f.IsZero() { | ||
output[pair.Key()] = pair.Value() | ||
} | ||
} |
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 here also not sure if reflect is a good approach.
for _, f := range configFiles.ConfigFiles { | ||
if f.Filename != "" { | ||
dir = filepath.Base(f.Filename) | ||
break | ||
} | ||
} |
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.
why do we need to iterate over the config files here? I don't know much about this part of the code, but would like to know what problem it solves. For example, In which cases would the filename be empty?
Go's `net` package [will unlink][1] for us, as long as we used Listen & friends to create the Unix socket. Go will even skip the unlink when the socket appears to be abstract (starts with a NUL, represented by an @), though we must be cautious to only create sockets with an abstract address on platforms that actually support it -- this caused [several][2] [bugs][3] before. [1]: https://pkg.go.dev/net#UnixListener.SetUnlinkOnClose [2]: docker/cli#4783 [3]: docker/cli#4863 Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
- What I did
Use
compose-go
to parse, interpolate and merge Compose configurations.As this library, under active maintenance and development by the Compose team, is up to date with the recent evolutions of the Compose Specification it will remove the potential divergence between the 2 code base, make the maintenance and evolution easier for everyone.
As a side effect, it would remove the necessity of using the
version
attribute. It disturbs users, the official Docker message is: "You don't need the version attribute anymore in your Compose files" and the CLI continue to introduce new versions of compose v3 file format- How I did it
Import the
compose-go
library, removed the duplicated code for structs, keep only the specific checks done on forbidden, unsupported and deprecated properties on the parsing part.Remove the interpolation and merging functions and let
compose-go
doing the jobAdd the specific mapping for
x-cluster-spec
extension attribut to match theClusterVolumeSpec
structRemove all the duplicated tests already done on the
compose-go
side- How to verify it
Run tests
Use average Compose configurations and check we're still producing the same output than the current version
- Description for the changelog
Use
compose-go
to manage Compose configuration files- A picture of a cute animal (not mandatory but encouraged)