diff --git a/README.md b/README.md index 67be459f..aa9e79d4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![fissile-logo](./docs/fissile-logo.png) -Fissile converts existing [BOSH] dev releases into docker images. +Fissile converts existing [BOSH] final or dev releases into docker images. It does this using just the releases, without a BOSH deployment, CPIs, or a BOSH agent. diff --git a/app/fissile.go b/app/fissile.go index 9ebc77e2..69cbb6df 100644 --- a/app/fissile.go +++ b/app/fissile.go @@ -52,7 +52,7 @@ func NewFissileApplication(version string, ui *termui.UI) *Fissile { } } -// ListPackages will list all BOSH packages within a list of dev releases +// ListPackages will list all BOSH packages within a list of releases func (f *Fissile) ListPackages(verbose bool) error { if len(f.releases) == 0 { return fmt.Errorf("Releases not loaded") @@ -90,7 +90,7 @@ func (f *Fissile) ListPackages(verbose bool) error { return nil } -// ListJobs will list all jobs within a list of dev releases +// ListJobs will list all jobs within a list of releases func (f *Fissile) ListJobs(verbose bool) error { if len(f.releases) == 0 { return fmt.Errorf("Releases not loaded") @@ -128,7 +128,7 @@ func (f *Fissile) ListJobs(verbose bool) error { return nil } -// ListProperties will list all properties in all jobs within a list of dev releases +// ListProperties will list all properties in all jobs within a list of releases func (f *Fissile) ListProperties(outputFormat OutputFormat) error { if len(f.releases) == 0 { return fmt.Errorf("Releases not loaded") @@ -190,7 +190,7 @@ func (f *Fissile) SerializeReleases() (map[string]interface{}, error) { return releases, nil } -// SerializeJobs will return all of the jobs within the dev releases, keyed by fingerprint +// SerializeJobs will return all of the jobs within the releases, keyed by fingerprint func (f *Fissile) SerializeJobs() (map[string]interface{}, error) { if len(f.releases) == 0 { return nil, fmt.Errorf("Releases not loaded") @@ -324,7 +324,7 @@ func (f *Fissile) Compile(stemcellImageName string, targetPath, roleManifestPath return err } - f.UI.Println(color.GreenString("Compiling packages for dev releases:")) + f.UI.Println(color.GreenString("Compiling packages for releases:")) for _, release := range releases { f.UI.Printf(" %s (%s)\n", color.YellowString(release.Name), color.MagentaString(release.Version)) } @@ -515,7 +515,7 @@ func (f *Fissile) GeneratePackagesRoleTarball(repository string, roleManifest *m return nil } -// GenerateRoleImages generates all role images using dev releases +// GenerateRoleImages generates all role images using releases func (f *Fissile) GenerateRoleImages(targetPath, registry, organization, repository, stemcellImageName, stemcellImageID, metricsPath string, noBuild, force bool, tagExtra string, roleNames []string, workerCount int, roleManifestPath, compiledPackagesPath, lightManifestPath, darkManifestPath, outputDirectory string) error { if len(f.releases) == 0 { return fmt.Errorf("Releases not loaded") @@ -681,9 +681,19 @@ func (f *Fissile) LoadReleases(releasePaths, releaseNames, releaseVersions []str releaseVersion = releaseVersions[idx] } - release, err := model.NewDevRelease(releasePath, releaseName, releaseVersion, cacheDir) - if err != nil { - return fmt.Errorf("Error loading release information: %s", err.Error()) + var release *model.Release + var err error + if _, err = isFinalReleasePath(releasePath); err == nil { + // For final releases, only can use release name and version defined in release.MF, cannot specify them through flags. + release, err = model.NewFinalRelease(releasePath) + if err != nil { + return fmt.Errorf("Error loading final release information: %s", err.Error()) + } + } else { + release, err = model.NewDevRelease(releasePath, releaseName, releaseVersion, cacheDir) + if err != nil { + return fmt.Errorf("Error loading dev release information: %s", err.Error()) + } } releases[idx] = release @@ -694,6 +704,34 @@ func (f *Fissile) LoadReleases(releasePaths, releaseNames, releaseVersions []str return nil } +func isFinalReleasePath(releasePath string) (bool, error) { + if err := util.ValidatePath(releasePath, true, "release directory"); err != nil { + return false, err + } + + if err := util.ValidatePath(filepath.Join(releasePath, "release.MF"), false, "release 'release.MF' file"); err != nil { + return false, err + } + + if err := util.ValidatePath(filepath.Join(releasePath, "dev_releases"), true, "release 'dev_releases' file"); err == nil { + return false, err + } + + if err := util.ValidatePath(filepath.Join(releasePath, "jobs"), true, "release 'jobs' directory"); err != nil { + return false, err + } + + if err := util.ValidatePath(filepath.Join(releasePath, "packages"), true, "release 'packages' directory"); err != nil { + return false, err + } + + if err := util.ValidatePath(filepath.Join(releasePath, "LICENSE"), false, "release 'LICENSE' file"); err != nil { + return false, err + } + + return true, nil +} + // getReleasesByName returns all named releases, or all releases if no names are given func (f *Fissile) getReleasesByName(releaseNames []string) ([]*model.Release, error) { if len(releaseNames) == 0 { diff --git a/cmd/root.go b/cmd/root.go index 6943354a..a0b52bdf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -48,7 +48,7 @@ var RootCmd = &cobra.Command{ Use: "fissile", Short: "The BOSH disintegrator", Long: ` -Fissile converts existing BOSH dev releases into docker images. +Fissile converts existing BOSH final or dev releases into docker images. It does this using just the releases, without a BOSH deployment, CPIs, or a BOSH agent. @@ -96,7 +96,7 @@ func init() { "release", "r", "", - "Path to dev BOSH release(s).", + "Path to final or dev BOSH release(s).", ) // We can't use slices here because of https://github.com/spf13/viper/issues/112 @@ -104,7 +104,7 @@ func init() { "release-name", "n", "", - "Name of a dev BOSH release; if empty, default configured dev release name will be used", + "Name of a dev BOSH release; if empty, default configured dev release name will be used; Final release always use the name in release.MF", ) // We can't use slices here because of https://github.com/spf13/viper/issues/112 @@ -112,7 +112,7 @@ func init() { "release-version", "v", "", - "Version of a dev BOSH release; if empty, the latest dev release will be used", + "Version of a dev BOSH release; if empty, the latest dev release will be used; Final release always use the version in release.MF", ) RootCmd.PersistentFlags().StringP( diff --git a/docs/generated/fissile.md b/docs/generated/fissile.md index 8205ebc2..1493f730 100644 --- a/docs/generated/fissile.md +++ b/docs/generated/fissile.md @@ -6,7 +6,7 @@ The BOSH disintegrator -Fissile converts existing BOSH dev releases into docker images. +Fissile converts existing BOSH final or dev releases into docker images. It does this using just the releases, without a BOSH deployment, CPIs, or a BOSH agent. @@ -19,9 +19,7 @@ agent. --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -42,4 +40,4 @@ agent. * [fissile show](fissile_show.md) - Has subcommands that display information about build artifacts. * [fissile version](fissile_version.md) - Displays fissile's version. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_build.md b/docs/generated/fissile_build.md index 8f8c8f93..b7e68bde 100644 --- a/docs/generated/fissile_build.md +++ b/docs/generated/fissile_build.md @@ -14,9 +14,7 @@ Has subcommands to build all images and necessary artifacts. --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -38,4 +36,4 @@ Has subcommands to build all images and necessary artifacts. * [fissile build kube](fissile_build_kube.md) - Creates Kubernetes configuration files. * [fissile build packages](fissile_build_packages.md) - Builds BOSH packages in a Docker container. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_build_cleancache.md b/docs/generated/fissile_build_cleancache.md index 2328b95c..ad4f97ac 100644 --- a/docs/generated/fissile_build_cleancache.md +++ b/docs/generated/fissile_build_cleancache.md @@ -20,9 +20,7 @@ fissile build cleancache --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -39,4 +37,4 @@ fissile build cleancache ### SEE ALSO * [fissile build](fissile_build.md) - Has subcommands to build all images and necessary artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_build_helm.md b/docs/generated/fissile_build_helm.md index 88cbb651..6c1c1b54 100644 --- a/docs/generated/fissile_build_helm.md +++ b/docs/generated/fissile_build_helm.md @@ -16,7 +16,6 @@ fissile build helm ``` -D, --defaults-file string Env files that contain defaults for the configuration variables --output-dir string Helm chart files will be written to this directory (default ".") - --tag-extra string Additional information to use in computing the image tags --use-memory-limits Include memory limits when generating helm chart (default true) ``` @@ -27,9 +26,7 @@ fissile build helm --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -46,4 +43,4 @@ fissile build helm ### SEE ALSO * [fissile build](fissile_build.md) - Has subcommands to build all images and necessary artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_build_images.md b/docs/generated/fissile_build_images.md index 805cb468..232a51c0 100644 --- a/docs/generated/fissile_build_images.md +++ b/docs/generated/fissile_build_images.md @@ -39,7 +39,6 @@ fissile build images --roles string Build only images with the given role name; comma separated. -s, --stemcell string The source stemcell --stemcell-id string Docker image ID for the stemcell (intended for CI) - --tag-extra string Additional information to use in computing the image tags ``` ### Options inherited from parent commands @@ -49,9 +48,7 @@ fissile build images --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -68,4 +65,4 @@ fissile build images ### SEE ALSO * [fissile build](fissile_build.md) - Has subcommands to build all images and necessary artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_build_kube.md b/docs/generated/fissile_build_kube.md index c84258aa..b5b9130d 100644 --- a/docs/generated/fissile_build_kube.md +++ b/docs/generated/fissile_build_kube.md @@ -16,7 +16,6 @@ fissile build kube ``` -D, --defaults-file string Env files that contain defaults for the parameters generated by kube --output-dir string Kubernetes configuration files will be written to this directory (default ".") - --tag-extra string Additional information to use in computing the image tags --use-memory-limits Include memory limits when generating kube configurations (default true) ``` @@ -27,9 +26,7 @@ fissile build kube --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -46,4 +43,4 @@ fissile build kube ### SEE ALSO * [fissile build](fissile_build.md) - Has subcommands to build all images and necessary artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_build_packages.md b/docs/generated/fissile_build_packages.md index 1b3cb730..196a7a32 100644 --- a/docs/generated/fissile_build_packages.md +++ b/docs/generated/fissile_build_packages.md @@ -42,9 +42,7 @@ fissile build packages --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -61,4 +59,4 @@ fissile build packages ### SEE ALSO * [fissile build](fissile_build.md) - Has subcommands to build all images and necessary artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_diff.md b/docs/generated/fissile_diff.md index aca738a3..cfd6b700 100644 --- a/docs/generated/fissile_diff.md +++ b/docs/generated/fissile_diff.md @@ -22,9 +22,7 @@ fissile diff --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -41,4 +39,4 @@ fissile diff ### SEE ALSO * [fissile](fissile.md) - The BOSH disintegrator -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_docs.md b/docs/generated/fissile_docs.md index 58bb0d3c..18c3ddfa 100644 --- a/docs/generated/fissile_docs.md +++ b/docs/generated/fissile_docs.md @@ -14,9 +14,7 @@ Has subcommands to create documentation for fissile. --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -36,4 +34,4 @@ Has subcommands to create documentation for fissile. * [fissile docs man](fissile_docs_man.md) - Generates man pages for fissile. * [fissile docs markdown](fissile_docs_markdown.md) - Generates markdown documentation for fissile. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_docs_autocomplete.md b/docs/generated/fissile_docs_autocomplete.md index f1be476e..3ba2c7b5 100644 --- a/docs/generated/fissile_docs_autocomplete.md +++ b/docs/generated/fissile_docs_autocomplete.md @@ -26,9 +26,7 @@ fissile docs autocomplete --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -45,4 +43,4 @@ fissile docs autocomplete ### SEE ALSO * [fissile docs](fissile_docs.md) - Has subcommands to create documentation for fissile. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_docs_man.md b/docs/generated/fissile_docs_man.md index c4b6d477..e3c4666e 100644 --- a/docs/generated/fissile_docs_man.md +++ b/docs/generated/fissile_docs_man.md @@ -24,9 +24,7 @@ fissile docs man --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -43,4 +41,4 @@ fissile docs man ### SEE ALSO * [fissile docs](fissile_docs.md) - Has subcommands to create documentation for fissile. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_docs_markdown.md b/docs/generated/fissile_docs_markdown.md index 267dab6e..e1a4fdc8 100644 --- a/docs/generated/fissile_docs_markdown.md +++ b/docs/generated/fissile_docs_markdown.md @@ -24,9 +24,7 @@ fissile docs markdown --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -43,4 +41,4 @@ fissile docs markdown ### SEE ALSO * [fissile docs](fissile_docs.md) - Has subcommands to create documentation for fissile. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_show.md b/docs/generated/fissile_show.md index 2688c2b8..6e45e355 100644 --- a/docs/generated/fissile_show.md +++ b/docs/generated/fissile_show.md @@ -14,9 +14,7 @@ Has subcommands that display information about build artifacts. --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -36,4 +34,4 @@ Has subcommands that display information about build artifacts. * [fissile show properties](fissile_show_properties.md) - Displays information about BOSH properties, per jobs. * [fissile show release](fissile_show_release.md) - Displays information about BOSH releases. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_show_image.md b/docs/generated/fissile_show_image.md index 81c68404..31806b68 100644 --- a/docs/generated/fissile_show_image.md +++ b/docs/generated/fissile_show_image.md @@ -19,9 +19,8 @@ fissile show image ### Options ``` - -D, --docker-only If the flag is set, only show images that are available on docker - --tag-extra string Additional information to use in computing the image tags - -S, --with-sizes If the flag is set, also show image virtual sizes; only works if the --docker-only flag is set + -D, --docker-only If the flag is set, only show images that are available on docker + -S, --with-sizes If the flag is set, also show image virtual sizes; only works if the --docker-only flag is set ``` ### Options inherited from parent commands @@ -31,9 +30,7 @@ fissile show image --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -50,4 +47,4 @@ fissile show image ### SEE ALSO * [fissile show](fissile_show.md) - Has subcommands that display information about build artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_show_properties.md b/docs/generated/fissile_show_properties.md index 6c0fb310..bf310bdc 100644 --- a/docs/generated/fissile_show_properties.md +++ b/docs/generated/fissile_show_properties.md @@ -21,9 +21,7 @@ fissile show properties --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -40,4 +38,4 @@ fissile show properties ### SEE ALSO * [fissile show](fissile_show.md) - Has subcommands that display information about build artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_show_release.md b/docs/generated/fissile_show_release.md index 129bd5d2..76ad00eb 100644 --- a/docs/generated/fissile_show_release.md +++ b/docs/generated/fissile_show_release.md @@ -21,9 +21,7 @@ fissile show release --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -40,4 +38,4 @@ fissile show release ### SEE ALSO * [fissile show](fissile_show.md) - Has subcommands that display information about build artifacts. -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/docs/generated/fissile_version.md b/docs/generated/fissile_version.md index ae5a5cee..dd6085fb 100644 --- a/docs/generated/fissile_version.md +++ b/docs/generated/fissile_version.md @@ -18,9 +18,7 @@ fissile version --config string config file (default is $HOME/.fissile.yaml) -d, --dark-opinions string Path to a BOSH deployment manifest file that contains properties that should not have opinionated defaults. --docker-organization string Docker organization used when referencing image names - --docker-password string Password for authenticated docker registry --docker-registry string Docker registry used when referencing image names - --docker-username string Username for authenticated docker registry -l, --light-opinions string Path to a BOSH deployment manifest file that contains properties to be used as defaults. -M, --metrics string Path to a CSV file to store timing metrics into. -o, --output string Choose output format, one of human, json, or yaml (currently only for 'show properties') (default "human") @@ -37,4 +35,4 @@ fissile version ### SEE ALSO * [fissile](fissile.md) - The BOSH disintegrator -###### Auto generated by spf13/cobra on 20-Oct-2017 +###### Auto generated by spf13/cobra on 12-Nov-2017 diff --git a/model/dev_release.go b/model/dev_release.go index 7f17cb1f..eb202397 100644 --- a/model/dev_release.go +++ b/model/dev_release.go @@ -18,6 +18,7 @@ func NewDevRelease(path, releaseName, version, boshCacheDir string) (*Release, e Name: releaseName, Version: version, DevBOSHCacheDir: boshCacheDir, + FinalRelease: false, } if err := release.validateDevPathStructure(); err != nil { diff --git a/model/final_release.go b/model/final_release.go new file mode 100644 index 00000000..9e566a14 --- /dev/null +++ b/model/final_release.go @@ -0,0 +1,101 @@ +package model + +import ( + "fmt" + "io/ioutil" + "path/filepath" + + "gopkg.in/yaml.v2" +) + +// NewFinalRelease will create an instance of a BOSH final release +func NewFinalRelease(path string) (release *Release, err error) { + release = &Release{ + Path: path, + Name: "", + Version: "", + FinalRelease: true, + } + + release.Name, err = release.getFinalReleaseName() + if err != nil { + return nil, err + } + + release.Version, err = release.getFinalReleaseVersion() + if err != nil { + return nil, err + } + + if err := release.loadMetadata(); err != nil { + return nil, err + } + + if err := release.loadPackages(); err != nil { + return nil, err + } + + if err := release.loadDependenciesForPackages(); err != nil { + return nil, err + } + + if err := release.loadJobs(); err != nil { + return nil, err + } + + if err := release.loadLicense(); err != nil { + return nil, err + } + + return release, nil +} + +func (r *Release) getFinalReleaseName() (name string, err error) { + var releaseConfig map[interface{}]interface{} + + releaseConfigContent, err := ioutil.ReadFile(r.getFinalReleaseConfigFile()) + if err != nil { + return "", err + } + + if err := yaml.Unmarshal([]byte(releaseConfigContent), &releaseConfig); err != nil { + return "", err + } + + if value, ok := releaseConfig["name"]; !ok { + return "", fmt.Errorf("name does not exist in release.MF file for release: %s", r.Path) + } else if name, ok = value.(string); !ok { + return "", fmt.Errorf("name was not a string in release.MF: %s, type: %T, value: %v", r.Path, value, value) + } + + return name, nil +} + +func (r *Release) getFinalReleaseVersion() (version string, err error) { + var releaseConfig map[interface{}]interface{} + + releaseConfigContent, err := ioutil.ReadFile(r.getFinalReleaseConfigFile()) + if err != nil { + return "", err + } + + if err := yaml.Unmarshal([]byte(releaseConfigContent), &releaseConfig); err != nil { + return "", err + } + + if value, ok := releaseConfig["version"]; !ok { + return "", fmt.Errorf("version does not exist in release.MF file for release: %s", r.Name) + } else if version, ok = value.(string); !ok { + return "", fmt.Errorf("version is not a string in release.MF: %s, type: %T, value: %v", r.Name, value, value) + } + + return version, nil +} + +func (r *Release) getFinalReleaseManifestFilename() string { + return "release.MF" +} + +func (r *Release) getFinalReleaseConfigFile() string { + return filepath.Join(r.Path, "release.MF") +} diff --git a/model/final_release_test.go b/model/final_release_test.go new file mode 100644 index 00000000..79c5e73c --- /dev/null +++ b/model/final_release_test.go @@ -0,0 +1,171 @@ +package model + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/SUSE/fissile/util" + + "github.com/stretchr/testify/assert" +) + +func TestFinalReleaseValidationOk(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release") + + _, err = NewFinalRelease(emptyFinalReleasePath) + + assert.NoError(err) +} + +func TestFinalReleaseSpecificNameOk(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release") + + release, err := NewFinalRelease(emptyFinalReleasePath) + + assert.NoError(err) + assert.Equal("test-final", release.Name) + assert.Equal("1", release.Version) +} + +func TestFinalReleaseMissingNameInMetaData(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release-missing-release-name") + + _, err = NewFinalRelease(emptyFinalReleasePath) + + assert.NotNil(err) + assert.Contains(err.Error(), "name does not exist in release.MF file for release") +} + +func TestFinalReleaseMissingVersionInMetaData(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release-missing-release-version") + + _, err = NewFinalRelease(emptyFinalReleasePath) + + assert.NotNil(err) + assert.Contains(err.Error(), "version does not exist in release.MF file for release") + //assert.Equal("test-final", release.Name) +} + +func TestFinalReleasePackagesOk(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release") + + release, err := NewFinalRelease(emptyFinalReleasePath) + + assert.NoError(err) + assert.NotNil(release) + + assert.Len(release.Packages, 2) + + barPkg, err := release.LookupPackage("bar") + assert.NoError(err) + + assert.Equal("bar", barPkg.Name) + assert.Equal("foo", barPkg.Dependencies[0].Name) +} + +func TestFinalReleasePackageExtractOk(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release") + + release, err := NewFinalRelease(emptyFinalReleasePath) + + assert.NoError(err) + assert.NotNil(release) + + assert.Len(release.Packages, 2) + + barPkg, err := release.LookupPackage("bar") + assert.NoError(err) + + tempDir, err := ioutil.TempDir("", "fissile-tests") + assert.NoError(err) + defer os.RemoveAll(tempDir) + + extractedPath, err := barPkg.Extract(tempDir) + assert.NoError(err) + + assert.Nil(util.ValidatePath(extractedPath, true, "extracted package dir")) +} + +func TestFinalReleaseJobsOk(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release") + + release, err := NewFinalRelease(emptyFinalReleasePath) + + assert.NoError(err) + assert.NotNil(release) + + assert.Len(release.Jobs, 2) + + barJob, err := release.LookupJob("bar") + assert.NoError(err) + + assert.Equal("bar", barJob.Name) + if assert.NotEmpty(barJob.Packages) { + assert.Equal("bar", barJob.Packages[0].Name) + } +} + +func TestFinalReleaseJobExtractOk(t *testing.T) { + assert := assert.New(t) + + workDir, err := os.Getwd() + assert.NoError(err) + + emptyFinalReleasePath := filepath.Join(workDir, "../test-assets/test-final-release") + + release, err := NewFinalRelease(emptyFinalReleasePath) + + assert.NoError(err) + assert.NotNil(release) + + assert.Len(release.Packages, 2) + + barJob, err := release.LookupJob("bar") + assert.NoError(err) + + tempDir, err := ioutil.TempDir("", "fissile-tests") + assert.NoError(err) + defer os.RemoveAll(tempDir) + + extractedPath, err := barJob.Extract(tempDir) + assert.NoError(err) + + assert.Nil(util.ValidatePath(extractedPath, true, "extracted job dir")) +} diff --git a/model/job.go b/model/job.go index 909d39b9..16bc7035 100644 --- a/model/job.go +++ b/model/job.go @@ -378,6 +378,10 @@ func (slice Jobs) Swap(i, j int) { } func (j *Job) jobArchivePath() string { + if j.Release.FinalRelease { + return filepath.Join(j.Release.Path, "jobs", j.Name+".tgz") + } + return filepath.Join(j.Release.DevBOSHCacheDir, j.SHA1) } diff --git a/model/job_test.go b/model/job_test.go index be70f5ad..beb710f5 100644 --- a/model/job_test.go +++ b/model/job_test.go @@ -16,223 +16,281 @@ import ( yaml "gopkg.in/yaml.v2" ) -func TestJobInfoOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathCacheDir := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathCacheDir) - assert.NoError(err) - - assert.Len(release.Jobs, 1) - const ntpdFingerprint = "9c168f583bc177f91e6ef6ef1eab1b4550b78b1e" - const ntpdVersion = ntpdFingerprint - const ntpdSHA1 = "8eeef09ae67e65aeb3257df402336de04822efc5" - - assert.Equal("ntpd", release.Jobs[0].Name) - assert.Equal(ntpdFingerprint, release.Jobs[0].Version) - assert.Equal(ntpdVersion, release.Jobs[0].Fingerprint) - assert.Equal(ntpdSHA1, release.Jobs[0].SHA1) - - jobPath := filepath.Join(ntpReleasePathCacheDir, ntpdSHA1) - assert.Equal(jobPath, release.Jobs[0].Path) +type FakeRelease struct { + ReleasePath string + FakeRelease Release +} - err = util.ValidatePath(jobPath, false, "") - assert.NoError(err) +type JobInfo struct { + Fingerprint string + Version string + SHA1 string + Path string } -func TestJobSha1Ok(t *testing.T) { +func TestDevAndFinalReleaseJob(t *testing.T) { assert := assert.New(t) workDir, err := os.Getwd() assert.NoError(err) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathCacheDir := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathCacheDir) + ntpDevReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") + ntpDevReleasePathCacheDir := filepath.Join(ntpDevReleasePath, "bosh-cache") + devRelease, err := NewDevRelease(ntpDevReleasePath, "", "", ntpDevReleasePathCacheDir) assert.NoError(err) - assert.Len(release.Jobs, 1) - - assert.Nil(release.Jobs[0].ValidateSHA1()) -} - -func TestJobSha1NotOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) + devJobPath := filepath.Join(ntpDevReleasePathCacheDir, "8eeef09ae67e65aeb3257df402336de04822efc5") + devJobInfo := JobInfo{ + Fingerprint: "9c168f583bc177f91e6ef6ef1eab1b4550b78b1e", + Version: "9c168f583bc177f91e6ef6ef1eab1b4550b78b1e", + SHA1: "8eeef09ae67e65aeb3257df402336de04822efc5", + Path: devJobPath, + } - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathCacheDir := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathCacheDir) + ntpFinalReleasePath := filepath.Join(workDir, "../test-assets/ntp-final-release") + finalRelease, err := NewFinalRelease(ntpFinalReleasePath) assert.NoError(err) - assert.Len(release.Jobs, 1) - - // Mess up the manifest signature - release.Jobs[0].SHA1 += "foo" + finalJobPath := filepath.Join(ntpFinalReleasePath, "jobs", finalRelease.Jobs[0].Name+".tgz") + finalJobInfo := JobInfo{ + Fingerprint: "99939d396a864a0df92aa3724e84d0e430c9298a", + Version: "99939d396a864a0df92aa3724e84d0e430c9298a", + SHA1: "26f8c7353305424f01d03b504cfa5a5262abc83d", + Path: finalJobPath, + } - assert.NotNil(release.Jobs[0].ValidateSHA1()) + t.Run("Dev release testJobInfoOk", testJobInfoOk(devRelease, devJobInfo)) + t.Run("Dev release testJobExtractOk", testJobExtractOk(devRelease)) + t.Run("Dev release testJobSha1Ok", testJobSha1Ok(devRelease)) + t.Run("Dev release testJobSha1NotOk", testJobSha1NotOk(devRelease)) + t.Run("Dev release testJobPackagesOk", testJobPackagesOk(devRelease, "ntp-4.2.8p2")) + t.Run("Dev release testJobTemplatesOk", testJobTemplatesOk(devRelease)) + t.Run("Dev release testJobPropertiesOk", testJobPropertiesOk(devRelease)) + t.Run("Dev release testGetJobPropertyOk", testGetJobPropertyOk(devRelease, 3)) + t.Run("Dev release testGetJobPropertyNotOk", testGetJobPropertyNotOk(devRelease, 3)) + t.Run("Dev release testJobLinksOk", testJobLinksOk(devRelease)) + t.Run("Dev release testJobsProperties", testJobsProperties(devRelease)) + + t.Run("Final release testJobInfoOk", testJobInfoOk(finalRelease, finalJobInfo)) + t.Run("Final release testJobExtractOk", testJobExtractOk(finalRelease)) + t.Run("Final release testJobSha1Ok", testJobSha1Ok(finalRelease)) + t.Run("Final release testJobSha1NotOk", testJobSha1NotOk(finalRelease)) + t.Run("Final release testJobPackagesOk", testJobPackagesOk(finalRelease, "ntp")) + t.Run("Final release testJobTemplatesOk", testJobTemplatesOk(finalRelease)) + t.Run("Final release testGetJobPropertyOk", testGetJobPropertyOk(finalRelease, 1)) + t.Run("Final release testFinalJobPropertiesOk", testFinalJobPropertiesOk(finalRelease)) + t.Run("Final release testGetJobPropertyNotOk", testGetJobPropertyNotOk(finalRelease, 1)) + t.Run("Final release testFinalJobsProperties", testFinalJobsProperties(finalRelease)) } -func TestJobExtractOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathCacheDir := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathCacheDir) - assert.NoError(err) +func testJobInfoOk(fakeRelease *Release, jobInfo JobInfo) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.Len(release.Jobs, 1) + assert.Len(fakeRelease.Jobs, 1) + assert.Equal("ntpd", fakeRelease.Jobs[0].Name) + assert.Equal(jobInfo.Fingerprint, fakeRelease.Jobs[0].Version) + assert.Equal(jobInfo.Version, fakeRelease.Jobs[0].Fingerprint) + assert.Equal(jobInfo.SHA1, fakeRelease.Jobs[0].SHA1) + assert.Equal(jobInfo.Path, fakeRelease.Jobs[0].Path) - tempDir, err := ioutil.TempDir("", "fissile-tests") - assert.NoError(err) - defer os.RemoveAll(tempDir) + err := util.ValidatePath(jobInfo.Path, false, "") + assert.NoError(err) + } +} - jobDir, err := release.Jobs[0].Extract(tempDir) - assert.NoError(err) +func testJobSha1Ok(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.Nil(util.ValidatePath(jobDir, true, "")) - assert.Nil(util.ValidatePath(filepath.Join(jobDir, "job.MF"), false, "")) + assert.Len(fakeRelease.Jobs, 1) + assert.Nil(fakeRelease.Jobs[0].ValidateSHA1()) + } } -func TestJobPackagesOk(t *testing.T) { - assert := assert.New(t) +func testJobSha1NotOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathCacheDir := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathCacheDir) - assert.NoError(err) + assert.Len(fakeRelease.Jobs, 1) - assert.Len(release.Jobs, 1) + // Mess up the manifest signature + fakeRelease.Jobs[0].SHA1 += "foo" + assert.NotNil(fakeRelease.Jobs[0].ValidateSHA1()) - assert.Len(release.Jobs[0].Packages, 1) - assert.Equal("ntp-4.2.8p2", release.Jobs[0].Packages[0].Name) + } } -func TestJobTemplatesOk(t *testing.T) { - assert := assert.New(t) +func testJobExtractOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - workDir, err := os.Getwd() - assert.NoError(err) + assert.Len(fakeRelease.Jobs, 1) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathCacheDir := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathCacheDir) - assert.NoError(err) + tempDir, err := ioutil.TempDir("", "fissile-tests") + assert.NoError(err) + defer os.RemoveAll(tempDir) - assert.Len(release.Jobs, 1) + jobDir, err := fakeRelease.Jobs[0].Extract(tempDir) + assert.NoError(err) - assert.Len(release.Jobs[0].Templates, 2) + assert.Nil(util.ValidatePath(jobDir, true, "")) + assert.Nil(util.ValidatePath(filepath.Join(jobDir, "job.MF"), false, "")) + } +} - assert.Contains([]string{"ctl.sh", "ntp.conf.erb"}, release.Jobs[0].Templates[0].SourcePath) - assert.Contains([]string{"ctl.sh", "ntp.conf.erb"}, release.Jobs[0].Templates[1].SourcePath) +func testJobPackagesOk(fakeRelease *Release, packageName string) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.Contains([]string{"etc/ntp.conf", "bin/ctl"}, release.Jobs[0].Templates[0].DestinationPath) - assert.Contains([]string{"etc/ntp.conf", "bin/ctl"}, release.Jobs[0].Templates[1].DestinationPath) + assert.Len(fakeRelease.Jobs, 1) + assert.Len(fakeRelease.Jobs[0].Packages, 1) + assert.Equal(packageName, fakeRelease.Jobs[0].Packages[0].Name) + } } -func TestJobPropertiesOk(t *testing.T) { - assert := assert.New(t) +func testJobTemplatesOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - workDir, err := os.Getwd() - assert.NoError(err) + assert.Len(fakeRelease.Jobs, 1) + assert.Len(fakeRelease.Jobs[0].Templates, 2) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) + assert.Contains([]string{"ctl.sh", "ntp.conf.erb"}, fakeRelease.Jobs[0].Templates[0].SourcePath) + assert.Contains([]string{"ctl.sh", "ntp.conf.erb"}, fakeRelease.Jobs[0].Templates[1].SourcePath) + + assert.Contains([]string{"etc/ntp.conf", "bin/ctl"}, fakeRelease.Jobs[0].Templates[0].DestinationPath) + assert.Contains([]string{"etc/ntp.conf", "bin/ctl"}, fakeRelease.Jobs[0].Templates[1].DestinationPath) + } +} - assert.Len(release.Jobs, 1) +func testJobPropertiesOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.Len(release.Jobs[0].Properties, 3) + assert.Len(fakeRelease.Jobs, 1) + assert.Len(fakeRelease.Jobs[0].Properties, 3) - assert.Equal("ntp_conf", release.Jobs[0].Properties[0].Name) - assert.Equal("ntpd's configuration file (ntp.conf)", release.Jobs[0].Properties[0].Description) - // Looks like properties are sorted by name. - assert.Equal("tor.private_key", release.Jobs[0].Properties[1].Name) - assert.Equal("M3Efvw4x3kzW+YBWR1oPG7hoUcPcFYXWxoYkYR5+KT4=", release.Jobs[0].Properties[1].Default) - assert.Equal("", release.Jobs[0].Properties[1].Description) + assert.Equal("ntp_conf", fakeRelease.Jobs[0].Properties[0].Name) + assert.Equal("ntpd's configuration file (ntp.conf)", fakeRelease.Jobs[0].Properties[0].Description) + // Looks like properties are sorted by name. + assert.Equal("tor.private_key", fakeRelease.Jobs[0].Properties[1].Name) + assert.Equal("M3Efvw4x3kzW+YBWR1oPG7hoUcPcFYXWxoYkYR5+KT4=", fakeRelease.Jobs[0].Properties[1].Default) + assert.Equal("", fakeRelease.Jobs[0].Properties[1].Description) + } } -func TestGetJobPropertyOk(t *testing.T) { - assert := assert.New(t) +func testFinalJobPropertiesOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - workDir, err := os.Getwd() - assert.NoError(err) + assert.Len(fakeRelease.Jobs, 1) + assert.Len(fakeRelease.Jobs[0].Properties, 1) + assert.Equal("ntp_conf", fakeRelease.Jobs[0].Properties[0].Name) + assert.Equal("ntpd's configuration file (ntp.conf)", fakeRelease.Jobs[0].Properties[0].Description) + } +} - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) +func testGetJobPropertyOk(fakeRelease *Release, jobPropertyLen int) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.Len(release.Jobs, 1) + assert.Len(fakeRelease.Jobs, 1) + assert.Len(fakeRelease.Jobs[0].Properties, jobPropertyLen) + property, err := fakeRelease.Jobs[0].getProperty("ntp_conf") - assert.Len(release.Jobs[0].Properties, 3) + assert.NoError(err) + assert.Equal("ntp_conf", property.Name) + } +} - property, err := release.Jobs[0].getProperty("ntp_conf") +func testGetJobPropertyNotOk(fakeRelease *Release, jobPropertyLen int) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.NoError(err) - assert.Equal("ntp_conf", property.Name) + assert.Len(fakeRelease.Jobs, 1) + assert.Len(fakeRelease.Jobs[0].Properties, jobPropertyLen) + _, err := fakeRelease.Jobs[0].getProperty("foo") + assert.NotNil(err) + assert.Contains(err.Error(), "not found in job") + } } -func TestGetJobPropertyNotOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) +func testJobLinksOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + + if !assert.Len(fakeRelease.Jobs, 1) { + return + } + + job, err := fakeRelease.LookupJob("ntpd") + if assert.NoError(err, "Failed to find ntpd job") { + assert.Equal([]jobConsumesInfo{ + jobConsumesInfo{jobLinkInfo: jobLinkInfo{Name: "ntp-server", Type: "ntpd"}}, + jobConsumesInfo{jobLinkInfo: jobLinkInfo{Type: "ntp"}, Optional: true}, + jobConsumesInfo{jobLinkInfo: jobLinkInfo{Type: "missing"}, Optional: true}, + }, job.DesiredConsumers) + assert.Equal(map[string]jobProvidesInfo{ + "ntp-server": {jobLinkInfo: jobLinkInfo{Name: "ntp-server", Type: "ntpd", JobName: "ntpd"}}, + "ntp-client": {jobLinkInfo: jobLinkInfo{Name: "ntp-client", Type: "ntp", JobName: "ntpd"}}, + }, job.AvailableProviders) + } + } +} - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) +func testJobsProperties(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.Len(release.Jobs, 1) + assert.Len(fakeRelease.Jobs, 1) - assert.Len(release.Jobs[0].Properties, 3) + workDir, err := os.Getwd() + assert.NoError(err) - _, err = release.Jobs[0].getProperty("foo") + lightOpinionsPath := filepath.Join(workDir, "../test-assets/ntp-opinions/opinions.yml") + darkOpinionsPath := filepath.Join(workDir, "../test-assets/ntp-opinions/dark-opinions.yml") + opinions, err := NewOpinions(lightOpinionsPath, darkOpinionsPath) + assert.NoError(err) - assert.NotNil(err) - assert.Contains(err.Error(), "not found in job") + properties, err := fakeRelease.Jobs[0].GetPropertiesForJob(opinions) + assert.Len(properties, 2) + actualJSON, err := json.Marshal(properties) + if assert.NoError(err) { + assert.JSONEq(`{ + "ntp_conf" : "zip.conf", + "with": { + "json": { + "default": { "key": "value" } + } + } + }`, string(actualJSON), "Unexpected properties") + } + } } -func TestJobLinksOk(t *testing.T) { - assert := assert.New(t) - workDir, err := os.Getwd() +func testFinalJobsProperties(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - assert.NoError(err) + assert.Len(fakeRelease.Jobs, 1) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) + workDir, err := os.Getwd() + assert.NoError(err) - if !assert.Len(release.Jobs, 1) { - return - } + lightOpinionsPath := filepath.Join(workDir, "../test-assets/ntp-opinions/opinions.yml") + darkOpinionsPath := filepath.Join(workDir, "../test-assets/ntp-opinions/dark-opinions.yml") + opinions, err := NewOpinions(lightOpinionsPath, darkOpinionsPath) + assert.NoError(err) - job, err := release.LookupJob("ntpd") - if assert.NoError(err, "Failed to find ntpd job") { - assert.Equal([]jobConsumesInfo{ - jobConsumesInfo{jobLinkInfo: jobLinkInfo{Name: "ntp-server", Type: "ntpd"}}, - jobConsumesInfo{jobLinkInfo: jobLinkInfo{Type: "ntp"}, Optional: true}, - jobConsumesInfo{jobLinkInfo: jobLinkInfo{Type: "missing"}, Optional: true}, - }, job.DesiredConsumers) - assert.Equal(map[string]jobProvidesInfo{ - "ntp-server": {jobLinkInfo: jobLinkInfo{Name: "ntp-server", Type: "ntpd", JobName: "ntpd"}}, - "ntp-client": {jobLinkInfo: jobLinkInfo{Name: "ntp-client", Type: "ntp", JobName: "ntpd"}}, - }, job.AvailableProviders) + properties, err := fakeRelease.Jobs[0].GetPropertiesForJob(opinions) + assert.Len(properties, 1) + actualJSON, err := json.Marshal(properties) + if assert.NoError(err) { + assert.JSONEq(`{ + "ntp_conf" : "zip.conf" + }`, string(actualJSON), "Unexpected properties") + } } } @@ -256,39 +314,6 @@ func TestJobsSort(t *testing.T) { assert.Equal(jobs[1].Name, "ddd") } -func TestJobsProperties(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - assert.Len(release.Jobs, 1) - - lightOpinionsPath := filepath.Join(workDir, "../test-assets/ntp-opinions/opinions.yml") - darkOpinionsPath := filepath.Join(workDir, "../test-assets/ntp-opinions/dark-opinions.yml") - opinions, err := NewOpinions(lightOpinionsPath, darkOpinionsPath) - assert.NoError(err) - - properties, err := release.Jobs[0].GetPropertiesForJob(opinions) - assert.Len(properties, 2) - actualJSON, err := json.Marshal(properties) - if assert.NoError(err) { - assert.JSONEq(`{ - "ntp_conf" : "zip.conf", - "with": { - "json": { - "default": { "key": "value" } - } - } - }`, string(actualJSON), "Unexpected properties") - } -} - func TestJobMarshal(t *testing.T) { testCases := []struct { value *Job diff --git a/model/package.go b/model/package.go index 58dbe99b..3d5afd69 100644 --- a/model/package.go +++ b/model/package.go @@ -144,6 +144,10 @@ func (p *Package) loadPackageDependencies() (err error) { } func (p *Package) packageArchivePath() string { + if p.Release.FinalRelease { + return filepath.Join(p.Release.Path, "packages", p.Name+".tgz") + } + return filepath.Join(p.Release.DevBOSHCacheDir, p.SHA1) } diff --git a/model/package_test.go b/model/package_test.go index 9c966764..e9284488 100644 --- a/model/package_test.go +++ b/model/package_test.go @@ -14,91 +14,105 @@ import ( yaml "gopkg.in/yaml.v2" ) -func TestPackageInfoOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - assert.Len(release.Packages, 1) - - assert.Equal("ntp-4.2.8p2", release.Packages[0].Name) - const ntpdFingerprint = "543219fbdaf6ec6f8af2956016055f2fb100d782" - const ntpdVersion = ntpdFingerprint - const ntpdSHA1 = "e41461c222b05f961350547da086569cc4264e54" - assert.Equal(ntpdFingerprint, release.Packages[0].Version) - assert.Equal(ntpdVersion, release.Packages[0].Fingerprint) - assert.Equal(ntpdSHA1, release.Packages[0].SHA1) - - packagePath := filepath.Join(ntpReleasePathBoshCache, ntpdSHA1) - assert.Equal(packagePath, release.Packages[0].Path) - - err = util.ValidatePath(packagePath, false, "") - assert.NoError(err) +type PackageInfo struct { + Name string + Fingerprint string + Version string + SHA1 string + Path string } -func TestPackageSHA1Ok(t *testing.T) { +func TestDevAndFinalReleasePackage(t *testing.T) { assert := assert.New(t) workDir, err := os.Getwd() assert.NoError(err) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) + ntpDevReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") + ntpDevReleasePathCacheDir := filepath.Join(ntpDevReleasePath, "bosh-cache") + devRelease, err := NewDevRelease(ntpDevReleasePath, "", "", ntpDevReleasePathCacheDir) assert.NoError(err) - assert.Len(release.Packages, 1) - - assert.Nil(release.Packages[0].ValidateSHA1()) -} - -func TestPackageSHA1NotOk(t *testing.T) { - assert := assert.New(t) + devPackagePath := filepath.Join(ntpDevReleasePathCacheDir, "e41461c222b05f961350547da086569cc4264e54") + devPackageInfo := PackageInfo{ + Name: "ntp-4.2.8p2", + Fingerprint: "543219fbdaf6ec6f8af2956016055f2fb100d782", + Version: "543219fbdaf6ec6f8af2956016055f2fb100d782", + SHA1: "e41461c222b05f961350547da086569cc4264e54", + Path: devPackagePath, + } - workDir, err := os.Getwd() + ntpFinalReleasePath := filepath.Join(workDir, "../test-assets/ntp-final-release") + finalRelease, err := NewFinalRelease(ntpFinalReleasePath) assert.NoError(err) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) + finalPackagePath := filepath.Join(ntpFinalReleasePath, "packages", "ntp.tgz") + finalPackageInfo := PackageInfo{ + Name: "ntp", + Fingerprint: "7ffae62452202409eedb58be773db7d1bfd890b7", + Version: "7ffae62452202409eedb58be773db7d1bfd890b7", + SHA1: "0285ebed26d7c8d21c2a3b8f5648ad9105d49a8d", + Path: finalPackagePath, + } - assert.Len(release.Packages, 1) + t.Run("Dev release testPackageInfoOk", testPackageInfoOk(devRelease, devPackageInfo)) + t.Run("Dev release testPackageSHA1Ok", testPackageSHA1Ok(devRelease)) + t.Run("Dev release testPackageSHA1NotOk", testPackageSHA1NotOk(devRelease)) + t.Run("Dev release testPackageExtractOk", testPackageExtractOk(devRelease)) - // Mess up the manifest signature - release.Packages[0].SHA1 += "foo" + t.Run("Final release testPackageInfoOk", testPackageInfoOk(finalRelease, finalPackageInfo)) + t.Run("Final release testPackageSHA1Ok", testPackageSHA1Ok(finalRelease)) + t.Run("Final release testPackageSHA1NotOk", testPackageSHA1NotOk(finalRelease)) + t.Run("Final release testPackageExtractOk", testPackageExtractOk(finalRelease)) - assert.NotNil(release.Packages[0].ValidateSHA1()) } -func TestPackageExtractOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) +func testPackageInfoOk(fakeRelease *Release, packageInfo PackageInfo) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + + assert.Len(fakeRelease.Packages, 1) + assert.Equal(packageInfo.Name, fakeRelease.Packages[0].Name) + assert.Equal(packageInfo.Fingerprint, fakeRelease.Packages[0].Fingerprint) + assert.Equal(packageInfo.Version, fakeRelease.Packages[0].Version) + assert.Equal(packageInfo.SHA1, fakeRelease.Packages[0].SHA1) + assert.Equal(packageInfo.Path, fakeRelease.Packages[0].Path) + err := util.ValidatePath(packageInfo.Path, false, "") + assert.NoError(err) + } +} - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) +func testPackageSHA1Ok(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + assert.Len(fakeRelease.Packages, 1) + assert.Nil(fakeRelease.Packages[0].ValidateSHA1()) + } +} - assert.Len(release.Packages, 1) +func testPackageSHA1NotOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + assert.Len(fakeRelease.Packages, 1) + // Mess up the manifest signature + fakeRelease.Packages[0].SHA1 += "foo" + assert.NotNil(fakeRelease.Packages[0].ValidateSHA1()) + } +} - tempDir, err := ioutil.TempDir("", "fissile-tests") - assert.NoError(err) - defer os.RemoveAll(tempDir) +func testPackageExtractOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + tempDir, err := ioutil.TempDir("", "fissile-tests") + assert.NoError(err) + defer os.RemoveAll(tempDir) - packageDir, err := release.Packages[0].Extract(tempDir) - assert.NoError(err) + packageDir, err := fakeRelease.Packages[0].Extract(tempDir) + assert.NoError(err) - assert.Nil(util.ValidatePath(packageDir, true, "")) - assert.Nil(util.ValidatePath(filepath.Join(packageDir, "packaging"), false, "")) + assert.Nil(util.ValidatePath(packageDir, true, "")) + assert.Nil(util.ValidatePath(filepath.Join(packageDir, "packaging"), false, "")) + } } func TestPackageMarshal(t *testing.T) { diff --git a/model/release.go b/model/release.go index 99b015e9..f236d94f 100644 --- a/model/release.go +++ b/model/release.go @@ -8,7 +8,6 @@ import ( "regexp" "github.com/SUSE/fissile/util" - "gopkg.in/yaml.v2" ) @@ -23,6 +22,7 @@ type Release struct { Version string Path string DevBOSHCacheDir string + FinalRelease bool manifest map[interface{}]interface{} } @@ -142,7 +142,6 @@ func (r *Release) loadPackages() (err error) { err = fmt.Errorf("Error trying to load release %s packages from YAML manifest: %s", r.Name, p) } }() - if packages, ok := r.manifest["packages"].([]interface{}); ok { for _, pkg := range packages { p, err := newPackage(r, pkg.(map[interface{}]interface{})) @@ -224,6 +223,10 @@ func (r *Release) jobsDirPath() string { } func (r *Release) manifestFilePath() string { + if r.FinalRelease { + return filepath.Join(r.Path, r.getFinalReleaseManifestFilename()) + } + return filepath.Join(r.getDevReleaseManifestsDir(), r.getDevReleaseManifestFilename()) } diff --git a/model/release_test.go b/model/release_test.go index 7d987a77..721c4fa9 100644 --- a/model/release_test.go +++ b/model/release_test.go @@ -12,17 +12,57 @@ import ( "github.com/stretchr/testify/assert" ) -func TestReleaseValidationOk(t *testing.T) { +type ReleaseInfo struct { + Name string + CommitHash string + UncommittedChanges bool + Version string +} + +func TestRelease(t *testing.T) { assert := assert.New(t) workDir, err := os.Getwd() assert.NoError(err) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - _, err = NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) + ntpDevReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") + ntpDevReleasePathCacheDir := filepath.Join(ntpDevReleasePath, "bosh-cache") + devRelease, err := NewDevRelease(ntpDevReleasePath, "", "", ntpDevReleasePathCacheDir) + assert.NoError(err) + devReleaseInfo := ReleaseInfo{ + Name: "ntp", + CommitHash: "4bc2f2fd", + UncommittedChanges: true, + Version: "2+dev.3", + } + + ntpFinalReleasePath := filepath.Join(workDir, "../test-assets/ntp-final-release") + finalRelease, err := NewFinalRelease(ntpFinalReleasePath) assert.NoError(err) + + finalReleaseInfo := ReleaseInfo{ + Name: "ntp", + CommitHash: "84166bb2", + UncommittedChanges: true, + Version: "4", + } + + t.Run("Dev release testReleaseMetadataOk", testReleaseMetadataOk(devRelease, devReleaseInfo)) + t.Run("Dev release testReleasePackagesOk", testReleasePackagesOk(devRelease)) + t.Run("Dev release testReleaseJobsOk", testReleaseJobsOk(devRelease)) + t.Run("Dev release testLookupPackageOk", testLookupPackageOk(devRelease, "ntp-4.2.8p2")) + t.Run("Dev release testLookupPackageNotOk", testLookupPackageNotOk(devRelease)) + t.Run("Dev release testLookupJobOk", testLookupJobOk(devRelease)) + t.Run("Dev release testLookupJobNotOk", testLookupJobNotOk(devRelease)) + + t.Run("Final release testReleaseMetadataOk", testReleaseMetadataOk(finalRelease, finalReleaseInfo)) + t.Run("Final release testReleasePackagesOk", testReleasePackagesOk(finalRelease)) + t.Run("Final release testReleaseJobsOk", testReleaseJobsOk(finalRelease)) + t.Run("Final release testLookupPackageOk", testLookupPackageOk(finalRelease, "ntp")) + t.Run("Final release testLookupPackageNotOk", testLookupPackageNotOk(finalRelease)) + t.Run("Final release testLookupJobOk", testLookupJobOk(finalRelease)) + t.Run("Final release testLookupJobNotOk", testLookupJobNotOk(finalRelease)) } func TestReleaseValidationNonExistingPath(t *testing.T) { @@ -39,6 +79,11 @@ func TestReleaseValidationNonExistingPath(t *testing.T) { assert.NotNil(err) assert.Contains(err.Error(), "does not exist") + + _, err = NewFinalRelease(releaseDir) + + assert.NotNil(err) + assert.Contains(err.Error(), "no such file or directory") } func TestReleaseValidationReleasePathIsAFile(t *testing.T) { @@ -54,6 +99,11 @@ func TestReleaseValidationReleasePathIsAFile(t *testing.T) { assert.NotNil(err) assert.Contains(err.Error(), "It should be a directory") + + _, err = NewFinalRelease(tempFile.Name()) + + assert.NotNil(err) + assert.Contains(err.Error(), "not a directory") } func TestReleaseValidationStructure(t *testing.T) { @@ -110,115 +160,71 @@ func TestReleaseValidationStructure(t *testing.T) { assert.NoError(err) } -func TestReleaseMetadataOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) +func testReleaseMetadataOk(fakeRelease *Release, releaseInfo ReleaseInfo) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - // These values come from the - // RELEASE-DIR/dev_releases/RELEASE-NAME/REL-V1+dev.V2.yml - assert.Equal("ntp", release.Name) - assert.Equal("4bc2f2fd", release.CommitHash) - assert.Equal(true, release.UncommittedChanges) - assert.Equal("2+dev.3", release.Version) + // For dev release, these values come from the + // RELEASE-DIR/dev_releases/RELEASE-NAME/REL-V1+dev.V2.yml + assert.Equal(releaseInfo.Name, fakeRelease.Name) + assert.Equal(releaseInfo.CommitHash, fakeRelease.CommitHash) + assert.Equal(releaseInfo.UncommittedChanges, fakeRelease.UncommittedChanges) + assert.Equal(releaseInfo.Version, fakeRelease.Version) + } } -func TestReleasePackagesOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - assert.Len(release.Packages, 1) +func testReleasePackagesOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + assert.Len(fakeRelease.Packages, 1) + } } -func TestReleaseJobsOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - assert.Len(release.Jobs, 1) +func testReleaseJobsOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + assert.Len(fakeRelease.Jobs, 1) + } } -func TestLookupPackageOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) +func testLookupPackageOk(fakeRelease *Release, packageName string) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - pkg, err := release.LookupPackage("ntp-4.2.8p2") - assert.NoError(err) + pkg, err := fakeRelease.LookupPackage(packageName) + assert.NoError(err) - assert.Equal("ntp-4.2.8p2", pkg.Name) + assert.Equal(packageName, pkg.Name) + } } -func TestLookupPackageNotOk(t *testing.T) { - assert := assert.New(t) +func testLookupPackageNotOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - workDir, err := os.Getwd() - assert.NoError(err) - - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - _, err = release.LookupPackage("foo") - assert.NotNil(err) + _, err := fakeRelease.LookupPackage("foo") + assert.NotNil(err) + } } -func TestLookupJobOk(t *testing.T) { - assert := assert.New(t) +func testLookupJobOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - workDir, err := os.Getwd() - assert.NoError(err) + job, err := fakeRelease.LookupJob("ntpd") + assert.NoError(err) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - job, err := release.LookupJob("ntpd") - assert.NoError(err) - - assert.Equal("ntpd", job.Name) + assert.Equal("ntpd", job.Name) + } } -func TestLookupJobNotOk(t *testing.T) { - assert := assert.New(t) - - workDir, err := os.Getwd() - assert.NoError(err) +func testLookupJobNotOk(fakeRelease *Release) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) - ntpReleasePath := filepath.Join(workDir, "../test-assets/ntp-release") - ntpReleasePathBoshCache := filepath.Join(ntpReleasePath, "bosh-cache") - release, err := NewDevRelease(ntpReleasePath, "", "", ntpReleasePathBoshCache) - assert.NoError(err) - - _, err = release.LookupJob("foo") - assert.NotNil(err) + _, err := fakeRelease.LookupJob("foo") + assert.NotNil(err) + } } func TestPackageDependencies(t *testing.T) { diff --git a/test-assets/ntp-final-release/LICENSE b/test-assets/ntp-final-release/LICENSE new file mode 100644 index 00000000..a84c3956 --- /dev/null +++ b/test-assets/ntp-final-release/LICENSE @@ -0,0 +1,25 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + diff --git a/test-assets/ntp-final-release/jobs/ntpd.tgz b/test-assets/ntp-final-release/jobs/ntpd.tgz new file mode 100644 index 00000000..72fb83e0 Binary files /dev/null and b/test-assets/ntp-final-release/jobs/ntpd.tgz differ diff --git a/test-assets/ntp-final-release/license.tgz b/test-assets/ntp-final-release/license.tgz new file mode 100644 index 00000000..1e4d1fc3 Binary files /dev/null and b/test-assets/ntp-final-release/license.tgz differ diff --git a/test-assets/ntp-final-release/packages/ntp.tgz b/test-assets/ntp-final-release/packages/ntp.tgz new file mode 100644 index 00000000..4fdd87b9 Binary files /dev/null and b/test-assets/ntp-final-release/packages/ntp.tgz differ diff --git a/test-assets/ntp-final-release/release.MF b/test-assets/ntp-final-release/release.MF new file mode 100644 index 00000000..5ad50d64 --- /dev/null +++ b/test-assets/ntp-final-release/release.MF @@ -0,0 +1,20 @@ +--- +packages: +- name: ntp + version: 7ffae62452202409eedb58be773db7d1bfd890b7 + fingerprint: 7ffae62452202409eedb58be773db7d1bfd890b7 + sha1: 0285ebed26d7c8d21c2a3b8f5648ad9105d49a8d + dependencies: [] +jobs: +- name: ntpd + version: 99939d396a864a0df92aa3724e84d0e430c9298a + fingerprint: 99939d396a864a0df92aa3724e84d0e430c9298a + sha1: 26f8c7353305424f01d03b504cfa5a5262abc83d +license: + version: 596316b93cdeded339f835660a5b50eac2ecc57a + fingerprint: 596316b93cdeded339f835660a5b50eac2ecc57a + sha1: 1bed533e3817f9789a6a63050139e03e39154af1 +commit_hash: 84166bb2 +uncommitted_changes: true +name: ntp +version: '4' diff --git a/test-assets/test-final-release-missing-release-name/release.MF b/test-assets/test-final-release-missing-release-name/release.MF new file mode 100644 index 00000000..286d4341 --- /dev/null +++ b/test-assets/test-final-release-missing-release-name/release.MF @@ -0,0 +1,5 @@ +commit_hash: d759e356 +uncommitted_changes: true +version: "1" +packages: [] +jobs: [] \ No newline at end of file diff --git a/test-assets/test-final-release-missing-release-version/release.MF b/test-assets/test-final-release-missing-release-version/release.MF new file mode 100644 index 00000000..3b0ab032 --- /dev/null +++ b/test-assets/test-final-release-missing-release-version/release.MF @@ -0,0 +1,5 @@ +commit_hash: d759e356 +uncommitted_changes: true +name: test-final +packages: [] +jobs: [] \ No newline at end of file diff --git a/test-assets/test-final-release/LICENSE b/test-assets/test-final-release/LICENSE new file mode 100644 index 00000000..e69de29b diff --git a/test-assets/test-final-release/jobs/bar.tgz b/test-assets/test-final-release/jobs/bar.tgz new file mode 100644 index 00000000..97d26652 Binary files /dev/null and b/test-assets/test-final-release/jobs/bar.tgz differ diff --git a/test-assets/test-final-release/jobs/foo.tgz b/test-assets/test-final-release/jobs/foo.tgz new file mode 100644 index 00000000..aa98da5a Binary files /dev/null and b/test-assets/test-final-release/jobs/foo.tgz differ diff --git a/test-assets/test-final-release/packages/bar.tgz b/test-assets/test-final-release/packages/bar.tgz new file mode 100644 index 00000000..ed604006 Binary files /dev/null and b/test-assets/test-final-release/packages/bar.tgz differ diff --git a/test-assets/test-final-release/packages/foo.tgz b/test-assets/test-final-release/packages/foo.tgz new file mode 100644 index 00000000..bf50494a Binary files /dev/null and b/test-assets/test-final-release/packages/foo.tgz differ diff --git a/test-assets/test-final-release/release.MF b/test-assets/test-final-release/release.MF new file mode 100644 index 00000000..209dbb05 --- /dev/null +++ b/test-assets/test-final-release/release.MF @@ -0,0 +1,25 @@ +commit_hash: d759e356 +uncommitted_changes: true +name: test-final +version: "1" +packages: +- name: bar + version: 5f914d68dd16640247bd04fccdcaf24dec214f78 + fingerprint: 5f914d68dd16640247bd04fccdcaf24dec214f78 + sha1: 68a95894b04649a62d1cb7543573f8ff1af50928 + dependencies: + - foo +- name: foo + version: 3ca47e4de81b570f2459ece373f26ca184f12a84 + fingerprint: 3ca47e4de81b570f2459ece373f26ca184f12a84 + sha1: c3323913873907e05dcafe32498cab7c4137548b + dependencies: [] +jobs: +- name: bar + version: b916ebf9dba489a7e4125c48e638268f7268ecb0 + fingerprint: b916ebf9dba489a7e4125c48e638268f7268ecb0 + sha1: 692bb3d14c4e49ec702affbf2c8360b23710f874 +- name: foo + version: d624f2f1d777626ea43f70922d6a22de6b573049 + fingerprint: d624f2f1d777626ea43f70922d6a22de6b573049 + sha1: 4d5bfffdc29414e16f840aa47a6baafc924d248b