-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Save assets in a state file on disk #388
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
Save assets in a state file on disk #388
Conversation
pkg/asset/store.go
Outdated
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.
Let's use JSON instead. Go's YAML implementation has a lot of trouble serializing and then deserializing accurately and YAML is a little too inviting for end users.
d3c6003 to
52bbb09
Compare
|
Have to redo the PR. Closing this one out. |
|
Please don't close out these pull requests. There is valuable discussion (maybe not so much in this case) that gets lost. Unless you are fundamentally changing the approach, I would reuse existing pull requests. |
|
@rajatchopra Any updates on this one? |
52bbb09 to
98eb6b5
Compare
98eb6b5 to
993b454
Compare
|
@yifan-gu @staebler PTAL Try this PR with a fresh install. Then repeat without deleting the target directory. No more asset re-generation. |
cb9a5ef to
240df82
Compare
cmd/openshift-install/main.go
Outdated
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 leaves the state file save if we error out in generating any assets above.
cmd/openshift-install/main.go
Outdated
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.
Fatal already os.Exit(1)
pkg/asset/stock/stock.go
Outdated
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.
??
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.
rebase relic :). Some similar code might be if we ever need to be able to construct the asset object from its name. Removed.
pkg/asset/store.go
Outdated
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 we not camel case. maybe this: .openshift_install_state.json
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.
.openshift_install_state.json now.
pkg/asset/store.go
Outdated
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.
drop this extra line.
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.
Ack.
pkg/asset/userprovided.go
Outdated
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 change seems orthogonal.
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.
Only part of it. The map in the argument does need to change. Fixed.
pkg/asset/store.go
Outdated
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.
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.
Fixed.
pkg/asset/store.go
Outdated
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 either be dropped or be something like looking up asset from state file
cmd/openshift-install/targets.go
Outdated
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.
also you can return error here; why Fatal?
1. Calls out on the Save function to persist the state file of all assets in a constant state file
2. Calls out on the Load function to partially load the contents of the state file into a new field in StoreImpl
3. In Save, marshaling as done as a map of type.String() to asset bytes:
i.e. stateMap[reflect.TypeOf(assetObject).String()] = marshalledBytes(assetObject)
reflect.TypeOf().String() is used as against reflect.Type.Name() function because Name returns the type name only, without scoping the package path.
See the implementation of type.Name() function where type.String() is used within: https://golang.org/src/reflect/type.go?#L874
4. Support for 'deferred unmarshal' for assets from state file:
Before a target is worked upon, the state file is loaded into the memory as partial asset state map.
The key of the map is the string representation of the asset type and the value is raw bytes that are left as is.
The idea is that 'fetch' will finally get the asset from the state file, only when needed. A utility function GetStateAsset has been provided to allow for deferred unmarshaling.
See example code to use the util function (as in the store's fetch function):
```
func (s *StoreImpl) fetch(asset Asset, indent string) error {
...
...
ok, err := s.GetStateAsset(asset)
if err != nil {
return errors.Wrapf("failed to unmarshal asset from state file: %v. Remove the state file and continue..", err)
}
if ok {
logrus.Debugf("%sAsset found in state file %v", indent, asset)
if s.assets == nil {
s.assets = make(map[reflect.Type]Asset)
}
s.assets[reflect.TypeOf(asset)] = asset
return nil
}
...
...
```
Alternatively, instead of passing the empty asset object, one can make a copy of the asset object and render it with contents from the state file:
```
newAsset := reflect.ValueOf(reflect.New(reflect.TypeOf(asset))).Elem().Interface()
ok, err := s.GetStateAsset(newAsset)
// now compare newAsset with asset itself
...
// and set the contents of asset from newAsset if needed:
reflect.ValueOf(asset).Elem().Set(reflect.ValueOf(newAsset).Elem())
```
Other notes:
The utility function GetStateAsset used in this commit such that if an asset is found in the state file, then its used directly. Further work will need to modify this behaviour so that a three way merge can happen between an asset found in the state file, found on disk, rendered by the Generate function.
Expose the fields of all Asset/WritableAsset objects so that we can Marshal/Unmarshal them from the state file.
Some of the fields clash with a function name implemented for the struct, so we have to change the field names themselves e.g. files cannot just be Files because there is a Files() function expected by the Asset interface.
Not all fields need be exported actually, because some fields can be constructed from the 'Files' field anyway. This optimization has not been done in this commit, it would perhaps need a custom UnmarshalJSON function to do that.
With this commit, all assets can be saved and loaded back properly. So, an example run of the openshift-install binary will look like this:
$ openshift-install manifests --dir=test --log-level=debug
$ # the above command generates the folders test/{manifests,tectonic} with all the files within
$ # it also genrates the state file in test/.openshift_install_state.json
$ # let's remove the manifest files and generate them again..
$ rm -rf test/{manifests,tectonic}
$ openshift-install manifests --dir=test --log-level=debug
$ # check that everything has been restored without actually generating anything
$ # run the install-config command even to create the install-config.yaml from state file:
$ openshift-install install-config --dir=test --log-level=debug
9315071 to
10f4ee5
Compare
crawford
left a comment
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
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: abhinavdahiya, crawford, rajatchopra The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/retest Please review the full test history for this PR and help us cut down flakes. |
2 similar comments
|
/retest Please review the full test history for this PR and help us cut down flakes. |
|
/retest Please review the full test history for this PR and help us cut down flakes. |
This saves us a few characters and gives us better handling when the string values themselves contain quotes (although only the former matters much in this case). The old manual quoting is from 971eea9 (pkg/asset: Save/Load functinality for assets into a state file, 2018-10-11, openshift#388).
Through f25e53a (Merge pull request openshift#388 from rajatchopra/state_file, 2018-10-12).
|
Do we need to poke a hole in this for the not-really-an-asset $ openshift-install version
openshift-install v0.2.0-14-g7cc49c8a92a86dd13ac66d1fd0560f679a36d1c0
Terraform v0.11.8
$ openshift-install --log-level=debug cluster
...
DEBUG Looking up asset from state file: *cluster.Cluster
DEBUG Asset found in state fileSo I have to manually blow away |
@wking A few things come to mind for me about this.
|
Or maybe they just directed that the asset be written to disk (which it is with the current master). The thing that's missing is that assets which have important side effects beside being written to disk (e.g. launching the cluster ;) aren't directly addressed by "generate this asset" semantics.
Maybe? It's not actually clear to me at what point we'd want to remove the state file. Once On the other hand, if you remove the cluster through some other path (e.g. |
|
We should instead check the asset store to see if the assets in the requested target have already been realized. If they have, we should do something different (e.g. tell the user that this operation is a no-op) rather than try to solve this down in the asset graph. |
pkg/asset:
Implement new funtions Save/Load for saving and loading the asset states
cmd/openshift-install:
Call out on the Save function to persist the state file of all assets in a constant state file