Skip to content

Commit

Permalink
refactor: use BOSH release manifest reader
Browse files Browse the repository at this point in the history
- refator: add test coverage for TestReadBOSHReleaseManifestsFromTarballs
- feat: add Stemcell method on BOSHReleaseManifest
- fix linter errors
- refactor: use new stemcell utility
  • Loading branch information
crhntr committed Jul 6, 2023
1 parent 94c4193 commit ac9600c
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 67 deletions.
73 changes: 9 additions & 64 deletions internal/builder/release_manifest_reader.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package builder

import (
"archive/tar"
"compress/gzip"
"crypto/sha1"
"encoding/hex"
"fmt"
"io"
"path/filepath"
"strings"

"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/osfs"

"gopkg.in/yaml.v2"
"github.com/pivotal-cf/kiln/pkg/tile"
"io"
"path/filepath"
)

type ReleaseManifest struct {
Expand All @@ -24,17 +20,6 @@ type ReleaseManifest struct {
StemcellVersion string `yaml:"-"`
}

// inputReleaseManifest is a subset of release.MF
type inputReleaseManifest struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
CompiledPackages []compiledPackage `yaml:"compiled_packages"`
}

type compiledPackage struct {
Stemcell string `yaml:"stemcell"`
}

type ReleaseManifestReader struct {
fs billy.Filesystem
}
Expand All @@ -54,54 +39,14 @@ func (r ReleaseManifestReader) Read(releaseTarball string) (Part, error) {
}
defer closeAndIgnoreError(file)

// TODO: use component.ReadReleaseManifest
// we could not do it yet due to a circular package reference where we import builder in the local release source

gr, err := gzip.NewReader(file)
if err != nil {
return Part{}, err
}
defer closeAndIgnoreError(gr)

tr := tar.NewReader(gr)

var header *tar.Header
for {
header, err = tr.Next()
if err != nil {
if err == io.EOF {
return Part{}, fmt.Errorf("could not find release.MF in %q", releaseTarball)
}

return Part{}, fmt.Errorf("error while reading %q: %s", releaseTarball, err)
}

if filepath.Base(header.Name) == "release.MF" {
break
}
}

var inputReleaseManifest inputReleaseManifest
inputReleaseManifestContents, err := io.ReadAll(tr)
if err != nil {
return Part{}, err // NOTE: cannot replicate this error scenario in a test
}

err = yaml.Unmarshal(inputReleaseManifestContents, &inputReleaseManifest)
inputReleaseManifest, err := tile.ReadProductTemplatePartFromBOSHReleaseTarball(file)
if err != nil {
return Part{}, err
}

var stemcellOS, stemcellVersion string
compiledPackages := inputReleaseManifest.CompiledPackages
if len(compiledPackages) > 0 {
inputStemcell := inputReleaseManifest.CompiledPackages[0].Stemcell
stemcellParts := strings.Split(inputStemcell, "/")
if len(stemcellParts) != 2 {
return Part{}, fmt.Errorf("Invalid format for compiled package stemcell inside release.MF (expected 'os/version'): %s", inputStemcell)
}
stemcellOS = stemcellParts[0]
stemcellVersion = stemcellParts[1]
stemcellOS, stemcellVersion, stemcellOK := inputReleaseManifest.Stemcell()
if !stemcellOK && len(inputReleaseManifest.CompiledPackages) > 0 {
return Part{}, fmt.Errorf("%s/%s has invalid stemcell: %q", inputReleaseManifest.Name, inputReleaseManifest.Version, inputReleaseManifest.CompiledPackages[0].Stemcell)
}

outputReleaseManifest := ReleaseManifest{
Expand All @@ -123,7 +68,7 @@ func (r ReleaseManifestReader) Read(releaseTarball string) (Part, error) {
return Part{}, err // NOTE: cannot replicate this error scenario in a test
}

outputReleaseManifest.SHA1 = fmt.Sprintf("%x", hash.Sum(nil))
outputReleaseManifest.SHA1 = hex.EncodeToString(hash.Sum(nil))

return Part{
File: releaseTarball,
Expand Down
6 changes: 3 additions & 3 deletions internal/builder/release_manifest_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ version: 1.2.3
Expect(gw.Close()).NotTo(HaveOccurred())

_, err = reader.Read(tarball.Name())
Expect(err).To(MatchError(fmt.Sprintf("could not find release.MF in %q", tarball.Name())))
Expect(err).To(MatchError("failed to find release.MF in tarball"))
})
})

Expand Down Expand Up @@ -220,7 +220,7 @@ version: 1.2.3
Expect(err).NotTo(HaveOccurred())

_, err = reader.Read(tarball.Name())
Expect(err).To(MatchError(fmt.Sprintf("could not find release.MF in %q", tarball.Name())))
Expect(err).To(MatchError("failed to find release.MF in tarball"))
})
})

Expand All @@ -242,7 +242,7 @@ version: 1.2.3
Expect(err).NotTo(HaveOccurred())

_, err = reader.Read(tarball.Name())
Expect(err).To(MatchError(fmt.Sprintf("error while reading %q: unexpected EOF", tarball.Name())))
Expect(err).To(MatchError("unexpected EOF"))
})
})

Expand Down
8 changes: 8 additions & 0 deletions pkg/tile/bosh_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"io/fs"
"os"
"path"
"strings"

"golang.org/x/exp/slices"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -104,6 +105,13 @@ type BOSHReleaseManifest struct {
Packages []BOSHReleasePackage `yaml:"packages"`
}

func (mf BOSHReleaseManifest) Stemcell() (string, string, bool) {
if len(mf.CompiledPackages) == 0 {
return "", "", false
}
return strings.Cut(mf.CompiledPackages[0].Stemcell, "/")
}

type BOSHReleaseTarball struct {
Manifest BOSHReleaseManifest

Expand Down
11 changes: 11 additions & 0 deletions pkg/tile/bosh_release_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tile_test

import (
"bytes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"io"
"os"
Expand Down Expand Up @@ -33,6 +34,16 @@ func TestReadReleaseFromFile(t *testing.T) {
please.Expect(err).NotTo(HaveOccurred())
}

func TestReadBOSHReleaseManifestsFromTarballs(t *testing.T) {
boshReleases, err := tile.ReadBOSHReleaseManifestsFromTarballs(os.DirFS("testdata"), "bpm-1.1.21-ubuntu-xenial-621.463.tgz", "bpm-1.1.21.tgz")
require.NoError(t, err)
require.Len(t, boshReleases, 2)
assert.Equal(t, "be5b1710f33128f6c864eae1d97effddb94dd3ac", boshReleases[0].SHA1)
assert.Equal(t, "519b78f2f3333a7b9c000bbef325e12a2f36996d", boshReleases[1].SHA1)
assert.Equal(t, "bpm-1.1.21-ubuntu-xenial-621.463.tgz", boshReleases[0].FilePath)
assert.Equal(t, "bpm-1.1.21.tgz", boshReleases[1].FilePath)
}

func TestReadProductTemplatePartFromBOSHReleaseTarball(t *testing.T) {
t.Run("when the release is compiled", func(t *testing.T) {
f, err := os.Open(filepath.Join("testdata", "bpm-1.1.21-ubuntu-xenial-621.463.tgz"))
Expand Down

0 comments on commit ac9600c

Please sign in to comment.