Skip to content

Commit

Permalink
Simplify file exports specification, bump version numbers (#188)
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanjli authored Apr 25, 2024
1 parent 3162db0 commit 23a44c3
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 60 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
## 0.7.0-alpha.4 - 2024-04-25

### Added

Expand All @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- (Breaking change; spec) The file exports specification has changed so that only a single target path (instead of a list of target paths) can be specified per file export object; accordingly, the field has been renamed from `targets` to `target`. Additionally, if the `source` path is left empty, it is interpreted to have the same value as the `target` path.
- (Breaking change; cli) The `--parallel` flag for various subcommands has now been consolidated and moved to the top level (e.g. `forklift --parallel plt cache-img` instead of `forklift plt cache-img --parallel`). Additionally, now the flag is enabled by default (because sequential downloading of images and bringup of Docker containers is so much slower than parallel downloading/bringup); to avoid parallel execution, use `--parallel=false` (e.g. `forklift --parallel=false plt cache-img`).
- (Breaking change; cli) `plt clone` no longer deletes the `.git` directory after cloning a pallet, because the new pallet staging functionality makes it feasible to keep a long-running local pallet which can change independently of what is actually applied on a computer.

Expand Down
8 changes: 4 additions & 4 deletions cmd/forklift/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,16 @@ const (
palletMinVersion = "v0.4.0"
// bundleMinVersion is the minimum supported Forklift version among staged pallet bundles. A
// bundle with a lower Forklift version cannot be used.
bundleMinVersion = "v0.7.0-alpha.1"
bundleMinVersion = "v0.7.0"
// newBundleVersion is the Forklift version reported in new staged pallet bundles made by Forklift.
// Older versions of the Forklift tool cannot use such bundles.
newBundleVersion = "v0.7.0-alpha.1"
newBundleVersion = "v0.7.0"
// newStageStoreVersion is the Forklift version reported in a stage store initialized by Forklift.
// Older versions of the Forklift tool cannot use the state store.
newStageStoreVersion = "v0.7.0-alpha.1"
newStageStoreVersion = "v0.7.0"
// fallbackVersion is the version reported which the Forklift tool reports itself as if its actual
// version is unknown.
fallbackVersion = "v0.7.0-alpha.2-dev"
fallbackVersion = "v0.7.1-dev"
)

var (
Expand Down
10 changes: 4 additions & 6 deletions docs/specs/00-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -1268,14 +1268,12 @@ This optional field of the `provides` subsection is an array of file export obje
- systemd-service
- networking
source: enable-interface-forwarding.service
targets:
- overlays/etc/systemd/system/enable-interface-forwarding.service
target: overlays/etc/systemd/system/enable-interface-forwarding.service
- description: Symlink to enable the systemd service
tags:
- systemd-symlink
source: enable-interface-forwarding.service.symlink
targets:
- overlays/etc/systemd/system/network-online.target.wants/enable-interface-forwarding.service
target: overlays/etc/systemd/system/network-online.target.wants/enable-interface-forwarding.service
```

A file export object consists of the following fields:
Expand All @@ -1292,15 +1290,15 @@ A file export object consists of the following fields:

- `source` is the path of the file to be exported, relative to the path of the package. The file must exist in the package's directory (or in a subdirectory).

- This field is required.
- This field is optional: if it's not specified, it's assumed to be the path set by the `target` field.

- Example:

```yaml
source: dhcp-and-dns.conf
```

- `targets` is an array of strings which are paths where the file should be exported to (e.g. by copying the file to those paths), relative to an export directory defined by the tool which implements the Forklift packaging specification.
- `target` is the path where the file should be exported to (e.g. by copying the file to that path), relative to an export directory defined by the tool which implements the Forklift packaging specification.

- This field is required.

Expand Down
29 changes: 15 additions & 14 deletions internal/app/forklift/bundles.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,20 +215,21 @@ func (b *FSBundle) WriteFileExports() error {
}
for _, export := range exports {
sourcePath := path.Join(resolved.Pkg.FS.Path(), export.Source)
for _, target := range export.Targets {
exportPath := path.Join(b.getExportsPath(), target)
if err := EnsureExists(filepath.FromSlash(path.Dir(exportPath))); err != nil {
return errors.Wrapf(
err, "couldn't make export directory %s in bundle", path.Dir(exportPath),
)
}
// TODO: once we upgrade to go1.23, use os.CopyFS instead (see
// https://github.com/golang/go/issues/62484)
if err := cp.Copy(
filepath.FromSlash(sourcePath), filepath.FromSlash(exportPath),
); err != nil {
return errors.Wrapf(err, "couldn't export file from %s to %s", sourcePath, exportPath)
}
if export.Source == "" {
sourcePath = path.Join(resolved.Pkg.FS.Path(), export.Target)
}
exportPath := path.Join(b.getExportsPath(), export.Target)
if err := EnsureExists(filepath.FromSlash(path.Dir(exportPath))); err != nil {
return errors.Wrapf(
err, "couldn't make export directory %s in bundle", path.Dir(exportPath),
)
}
// TODO: once we upgrade to go1.23, use os.CopyFS instead (see
// https://github.com/golang/go/issues/62484)
if err := cp.Copy(
filepath.FromSlash(sourcePath), filepath.FromSlash(exportPath),
); err != nil {
return errors.Wrapf(err, "couldn't export file from %s to %s", sourcePath, exportPath)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions internal/app/forklift/pallets-deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func (d *ResolvedDepl) DefinesApp() (bool, error) {
func (d *ResolvedDepl) GetFileExportTargets() ([]string, error) {
exportTargets := make([]string, 0)
for _, export := range d.Pkg.Def.Deployment.Provides.FileExports {
exportTargets = append(exportTargets, export.Targets...)
exportTargets = append(exportTargets, export.Target)
}
enabledFeatures, err := d.EnabledFeatures()
if err != nil {
Expand All @@ -168,7 +168,7 @@ func (d *ResolvedDepl) GetFileExportTargets() ([]string, error) {
}
for _, feature := range enabledFeatures {
for _, export := range feature.Provides.FileExports {
exportTargets = append(exportTargets, export.Targets...)
exportTargets = append(exportTargets, export.Target)
}
}
slices.Sort(exportTargets)
Expand Down
9 changes: 5 additions & 4 deletions pkg/core/packages-models.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,9 @@ type FileExportRes struct {
// Tags is a list of strings associated with the file export. Tags are not considered in checking
// resource constraints.
Tags []string `yaml:"tags,omitempty"`
// Source is the path in the package of the file to be exported.
Source string `yaml:"source"`
// Targets is a list of paths where the file will be exported to, relative to an export directory.
Targets []string `yaml:"targets"`
// Source is the path in the package of the file to be exported. If omitted, the source path will
// be inferred from the Target path.
Source string `yaml:"source,omitempty"`
// Target is the path where the file will be exported to, relative to an export directory.
Target string `yaml:"target"`
}
32 changes: 3 additions & 29 deletions pkg/core/packages-resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,9 @@ func SplitFilesetsByPath(filesetRes []AttachedRes[FilesetRes]) (split []Attached
// CheckConflict checks whether the file export resource, represented by the FileExportRes
// instance, conflicts with the candidate file export resource.
func (r FileExportRes) CheckConflict(candidate FileExportRes) (errs []error) {
if len(r.Targets) == 0 || len(candidate.Targets) == 0 {
errs = append(errs, errors.New("no specified file export targets"))
return errs
}

errs = append(errs, checkConflictingPathsWithParents(r.Targets, candidate.Targets)...)
errs = append(errs, checkConflictingPathsWithParents(
[]string{r.Target}, []string{candidate.Target})...,
)

// Tags should be ignored in checking conflicts
return errs
Expand Down Expand Up @@ -420,26 +417,3 @@ func pathMatchesParent(
}
return false, ""
}

// SplitFileExportsByTarget produces a slice of file export resources from the input slice, where
// each file export resource in the input slice with multiple paths targets results in multiple
// corresponding file export resources with one target path each.
func SplitFileExportsByTarget(
fileExportRes []AttachedRes[FileExportRes],
) (split []AttachedRes[FileExportRes]) {
split = make([]AttachedRes[FileExportRes], 0, len(fileExportRes))
for _, fileExport := range fileExportRes {
if len(fileExport.Res.Targets) == 0 {
split = append(split, fileExport)
}
for _, path := range fileExport.Res.Targets {
pathFileExport := fileExport.Res
pathFileExport.Targets = []string{path}
split = append(split, AttachedRes[FileExportRes]{
Res: pathFileExport,
Source: fileExport.Source,
})
}
}
return split
}

0 comments on commit 23a44c3

Please sign in to comment.