Conversation
Signed-off-by: Paul Mars <paul.mars@canonical.com>
|
letFunny
left a comment
There was a problem hiding this comment.
First review. I am missing a couple of files but I wanted to publish it as quickly as possible so we have more time to iterate. This is looking great Paul, many things are looking dead simple which is always an extremely good sign. I have written some comments about how to make the PR shorter and how to make it, hopefully, even simpler. Let me know what you think.
I see some of the comments are similar to past discussions we had in upils#1. We spent some effort there, so please make sure all the comments were carried over to this one.
| } | ||
| } | ||
|
|
||
| mfest, err := slicer.SelectValidManifest(cmd.RootDir, release) |
There was a problem hiding this comment.
In general our philosophy is that we should be able to cut a release from main at any point in time. That is, if we ever do a bug fix we should be able to release a point version. This is changing how Chisel works in folders with a manifest and it is not the correct behavior (yet) so I would prefer if we could gate this functionality over a environmental variable or a debug command or any other mechanism.
internal/fsutil/move.go
Outdated
| case 0, fs.ModeSymlink: | ||
| err = os.Rename(srcPath, dstPath) | ||
| case fs.ModeDir: | ||
| err = createDir(&CreateOptions{ |
There was a problem hiding this comment.
This is not moving the directory, it is left behind. It is also unexpected when an API is called Move and it moves the directory without its contents.
There was a problem hiding this comment.
You are right, "move" might not be the right name. What about:
- "Sync"?
- "Install"? I really like this one. Even if our strategy to install the content might be slightly different than the
installcommand, the feature is the same I think. - "Populate"?
internal/slicer/slicer.go
Outdated
| targetDir = filepath.Join(dir, targetDir) | ||
| } | ||
|
|
||
| var originalTargetDir string |
There was a problem hiding this comment.
A different way of doing it is to extract what used to be the Run function into another one and have Run call into that with different target dir and then upgrade (see extract.go for Run vs extractData). Do you think it will be clearer this way?
There was a problem hiding this comment.
I have no strong opinion for one or the other. It is unclear to me what lead extractData to be split into it's own function. Can you share the reason?
There was a problem hiding this comment.
It was already like that when I joined :). IMO it is better to split than to carry more data around and "fake" it bypassing the interface by overriding target and copying original.
It is also a cleaner abstraction as it doesn't need the rest of the code and will make the function shorter (even if marginally).
letFunny
left a comment
There was a problem hiding this comment.
The final set of files. Thanks again Paul for working on this.
| chisel_release="./release_${RELEASE}" | ||
| mkdir -p ${chisel_release}/slices | ||
|
|
||
| ref_chisel_release="ref-chisel-release_${RELEASE}" | ||
| git clone --depth=1 -b ${OS}-${RELEASE} \ | ||
| https://github.com/canonical/chisel-releases $ref_chisel_release | ||
|
|
||
| cp ${ref_chisel_release}/chisel.yaml ${chisel_release}/chisel.yaml | ||
|
|
||
| cat >${chisel_release}/slices/base-files.yaml <<'EOF' | ||
| package: base-files | ||
|
|
||
| slices: | ||
| slice-a: | ||
| contents: | ||
| /etc/debian_version: | ||
| slice-b: | ||
| contents: | ||
| /etc/issue: | ||
| manifest: | ||
| contents: | ||
| /chisel/**: {generate: manifest} | ||
| EOF |
There was a problem hiding this comment.
In my opinion, this is a bit heavy for what we need to test. We really do not care about testing the different releases as the release itself should not be important. I think you are correct in adding a simplified base-files.yaml manually, but I would take it a step further and add a release similar to pro-archives / unmaintained tests.
This is only a suggestion, I don't have a strong opinion, both work.
tests/recut/task.yaml
Outdated
| EXTRA_OPTIONS="--ignore=unmaintained " | ||
| fi | ||
|
|
||
| # First cut generates manifest and installs slice-a |
There was a problem hiding this comment.
| # First cut generates manifest and installs slice-a | |
| # First cut generates manifest and installs slice-a. |
Remember to punctuate comments please :)
| test -s ${rootfs_folder}/etc/debian_version | ||
| test -f ${rootfs_folder}/chisel/manifest.wall | ||
|
|
||
| # Remove a file from the first slice |
There was a problem hiding this comment.
Please add a TODO here saying that this is not expected behavior of the final feature. We should highlight in the test that this is only temporary.
I think what you are trying to test is that the content of pre-installed slices gets updated. What I would do is to change the contents and change the manifest to contain the new hash. The test will then verify that the file was updated. This will work now and in the future as it is highlighting the correct behavior.
internal/slicer/slicer_test.go
Outdated
| "/dir/file": "file 0644 cc55e2ec {test-package_third}", | ||
| }, | ||
| }, { | ||
| summary: "Recut removes obsolete paths when selection shrinks", |
There was a problem hiding this comment.
I think we are pushing this table too much now. This should really be test for the inner function, i.e. the equivalent of extract_data we discus in the other comments (not saying you should call internal function, I am just talking about conceptually).
I think we need a different test table that verifies re-cut and will take different data. You can have a release (maybe with a default release) and two inputs for the slices installed. The test installation will install version one and then call cut again. Compared to the current version, it is less leaky of the report abstraction as we don't need to build it manually, it is more faithful to what the real execution looks like and it is also far simpler to read and write as we are talking about normal chisel releases file contents, not the intricacies of the report with slice attribution.
There was a problem hiding this comment.
I expect the file to change substantially so I will not comment on the rest for now.
| hash string | ||
| } | ||
| var selected *manifest.Manifest | ||
| schemaManifest := make(map[string]manifestHash) |
There was a problem hiding this comment.
There is only one valid schema, why not keep a single variable with the expected hash that starts empty and then, when filled, is used to compare manifests?
| var selected *manifest.Manifest | ||
| schemaManifest := make(map[string]manifestHash) | ||
| for _, mfestPath := range manifestPaths { | ||
| err := func() error { |
There was a problem hiding this comment.
Why do we need this closure?
| defer r.Close() | ||
| mfest, err := manifest.Read(r) | ||
| if err != nil { | ||
| return err |
There was a problem hiding this comment.
This will not work correctly unless you add a custom error for the invalid schema and verify it here, I remember we discussed this a number of times in the other PR. Is there a test with a manifest with a different version that is valid jsonwall? I may have missed it.
| if !ok { | ||
| schemaManifest[mfest.Schema()] = manifestHash{mfestPath, mfestHash} | ||
| } else if refMfest.hash != mfestHash { | ||
| return fmt.Errorf("inconsistent manifests: %q and %q", refMfest.path, mfestPath) | ||
| } | ||
|
|
||
| if selected == nil || manifestutil.CompareSchemas(mfest.Schema(), selected.Schema()) > 0 { | ||
| selected = mfest | ||
| } |
There was a problem hiding this comment.
This is a bit weird, I would remove this logic until we have a need for it (see my other comment). We need to verify schema matches expected and matches hash (if set). This is trying to predict the future, but let's not anticipate small details about code when not needed.
Also, as a side-node, checking the hash for each version is different from:
Consistency with all other manifests with the same schema is verified so the selection is deterministic.
which I read as, verify all manifests of the selected schema. Is that what we want? (we probably don't want to have this discussion and we want to simplify it further instead).
This commit enables Chisel detecting the target directory contains the result
of a previous execution to then operate an upgrade of the content. This initial
simple implementation has the the limitation that content (files, symlinks) is
systematically replaced, even if identical. As a consequences:
different and thus the new OCI layer contains duplicated files.