diff --git a/internal/core/box.go b/internal/core/box.go index 23a5675f3..b68a37f60 100644 --- a/internal/core/box.go +++ b/internal/core/box.go @@ -2,6 +2,8 @@ package core import ( "errors" + "io/ioutil" + "net/http" "os" "time" @@ -9,6 +11,7 @@ import ( "github.com/hashicorp/go-version" "github.com/hashicorp/vagrant-plugin-sdk/core" "github.com/hashicorp/vagrant/internal/server/proto/vagrant_server" + "github.com/mitchellh/mapstructure" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -20,9 +23,18 @@ type Box struct { logger hclog.Logger } -func (b *Box) loadMetadata() (metadata core.BoxMetadata) { - // TODO: need box metadata implementation - return +func (b *Box) loadMetadata() (metadata *BoxMetadata, err error) { + resp, err := http.Get(b.box.MetadataUrl) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return LoadBoxMetadata(data) } func (b *Box) matches(box core.Box) (bool, error) { @@ -72,8 +84,27 @@ func (b *Box) Directory() (path string, err error) { // and provider. If the box doesn't have an update that satisfies the // constraints, it will return nil. func (b *Box) HasUpdate(version string) (updateAvailable bool, err error) { - // TODO: need box metadata - return + metadata, err := b.loadMetadata() + if err != nil { + return false, err + } + versionConstraint := "" + if version == "" { + versionConstraint = "> " + b.box.Version + } else { + versionConstraint = version + ", " + "> " + b.box.Version + } + result, err := metadata.Version( + versionConstraint, + &BoxVersionProvider{Name: b.box.Provider}, + ) + if err != nil { + return false, err + } + if result == nil { + return false, nil + } + return true, nil } // Checks if this box is in use according to the given machine @@ -104,8 +135,11 @@ func (b *Box) InUse(index core.TargetIndex) (inUse bool, err error) { } func (b *Box) Metadata() (metadata core.BoxMetadataMap, err error) { - // TODO - return + meta, err := b.loadMetadata() + if err != nil { + return nil, err + } + return metadata, mapstructure.Decode(meta, &metadata) } func (b *Box) MetadataURL() (url string, err error) { diff --git a/internal/core/box_test.go b/internal/core/box_test.go index 9eae66c17..a3348cf78 100644 --- a/internal/core/box_test.go +++ b/internal/core/box_test.go @@ -24,6 +24,21 @@ func newTestBox() *Box { } } +func hashicorpBionicTestBox() *Box { + return &Box{ + box: &vagrant_server.Box{ + Id: "123", + Provider: "virtualbox", + Version: "0.0.282", + Directory: "/tmp/boxes", + Metadata: map[string]string{}, + MetadataUrl: "https://app.vagrantup.com/hashicorp/boxes/bionic64.json", + Name: "hashicorp/bionic64", + LastUpdate: timestamppb.Now(), + }, + } +} + func TestBoxAutomaticUpdateCheckAllowed(t *testing.T) { testBox := newTestBox() // just did automated check @@ -75,3 +90,33 @@ func TestCompare(t *testing.T) { _, err = testBox.Compare(otherBox) require.Error(t, err) } + +func TestHasUpdate(t *testing.T) { + box := hashicorpBionicTestBox() + + // Older box + box.box.Version = "0.0.282" + result, err := box.HasUpdate("") + if err != nil { + t.Errorf("Failed to check for update") + } + require.True(t, result) + + // Newer box + box.box.Version = "99.9.282" + result2, err := box.HasUpdate("") + if err != nil { + t.Errorf("Failed to check for update") + } + require.False(t, result2) +} + +func TestMetadata(t *testing.T) { + box := hashicorpBionicTestBox() + result, err := box.Metadata() + if err != nil { + t.Errorf("Failed to get metadata") + } + require.NotNil(t, result) + require.Equal(t, "hashicorp/bionic64", result["Name"]) +}