Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
annotations: Improve asset annotation handling
Browse files Browse the repository at this point in the history
Make `asset.go` the arbiter of asset annotations by removing all asset
annotations lists from other parts of the codebase.

This makes the code simpler, easier to maintain, and more robust.

Specifically, the previous behaviour was inconsistent as the following
ways:

- `createAssets()` in `sandbox.go` was not handling the following asset
  annotations:

    - firmware:
      - `io.katacontainers.config.hypervisor.firmware`
      - `io.katacontainers.config.hypervisor.firmware_hash`

    - hypervisor:
      - `io.katacontainers.config.hypervisor.path`
      - `io.katacontainers.config.hypervisor.hypervisor_hash`

    - hypervisor control binary:
      - `io.katacontainers.config.hypervisor.ctlpath`
      - `io.katacontainers.config.hypervisor.hypervisorctl_hash`

    - jailer:
      - `io.katacontainers.config.hypervisor.jailer_path`
      - `io.katacontainers.config.hypervisor.jailer_hash`

- `addAssetAnnotations()` in the `oci` package was not handling the
  following asset annotations:

    - hypervisor:
      - `io.katacontainers.config.hypervisor.path`
      - `io.katacontainers.config.hypervisor.hypervisor_hash`

    - hypervisor control binary:
      - `io.katacontainers.config.hypervisor.ctlpath`
      - `io.katacontainers.config.hypervisor.hypervisorctl_hash`

    - jailer:
      - `io.katacontainers.config.hypervisor.jailer_path`
      - `io.katacontainers.config.hypervisor.jailer_hash`

This change fixes the bug where specifying a custom hypervisor path via an
asset annotation was having no effect.

Fixes: #3030.

Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
  • Loading branch information
jodh-intel committed Nov 4, 2020
1 parent 7d9860d commit 6a5eb0d
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 96 deletions.
38 changes: 38 additions & 0 deletions virtcontainers/hypervisor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,41 @@ func TestGenerateVMSocket(t *testing.T) {
assert.NotZero(vsock.ContextID)
assert.NotZero(vsock.Port)
}

func TestAssetPath(t *testing.T) {
assert := assert.New(t)

// Minimal config containing values for all asset annotation options.
// The values are "paths" (start with a slash), but end with the
// annotation name.
cfg := HypervisorConfig{
HypervisorPath: "/" + "io.katacontainers.config.hypervisor.path",
HypervisorCtlPath: "/" + "io.katacontainers.config.hypervisor.ctlpath",

KernelPath: "/" + "io.katacontainers.config.hypervisor.kernel",

ImagePath: "/" + "io.katacontainers.config.hypervisor.image",
InitrdPath: "/" + "io.katacontainers.config.hypervisor.initrd",

FirmwarePath: "/" + "io.katacontainers.config.hypervisor.firmware",
JailerPath: "/" + "io.katacontainers.config.hypervisor.jailer_path",
}

for _, asset := range types.AssetTypes() {
msg := fmt.Sprintf("asset: %v", asset)

annoPath, annoHash, err := asset.Annotations()
assert.NoError(err, msg)

msg += fmt.Sprintf(", annotation path: %v, annotation hash: %v", annoPath, annoHash)

p, err := cfg.assetPath(asset)
assert.NoError(err, msg)

assert.NotEqual(p, annoPath, msg)
assert.NotEqual(p, annoHash, msg)

expected := fmt.Sprintf("/%s", annoPath)
assert.Equal(expected, p, msg)
}
}
23 changes: 11 additions & 12 deletions virtcontainers/pkg/oci/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,11 @@ func SandboxID(spec specs.Spec) (string, error) {
}

func addAnnotations(ocispec specs.Spec, config *vc.SandboxConfig) error {
addAssetAnnotations(ocispec, config)
err := addAssetAnnotations(ocispec, config)
if err != nil {
return err
}

if err := addHypervisorConfigOverrides(ocispec, config); err != nil {
return err
}
Expand All @@ -345,17 +349,10 @@ func addAnnotations(ocispec specs.Spec, config *vc.SandboxConfig) error {
return nil
}

func addAssetAnnotations(ocispec specs.Spec, config *vc.SandboxConfig) {
assetAnnotations := []string{
vcAnnotations.KernelPath,
vcAnnotations.ImagePath,
vcAnnotations.InitrdPath,
vcAnnotations.FirmwarePath,
vcAnnotations.KernelHash,
vcAnnotations.ImageHash,
vcAnnotations.InitrdHash,
vcAnnotations.FirmwareHash,
vcAnnotations.AssetHashType,
func addAssetAnnotations(ocispec specs.Spec, config *vc.SandboxConfig) error {
assetAnnotations, err := types.AssetAnnotations()
if err != nil {
return err
}

for _, a := range assetAnnotations {
Expand All @@ -366,6 +363,8 @@ func addAssetAnnotations(ocispec specs.Spec, config *vc.SandboxConfig) {

config.Annotations[a] = value
}

return nil
}

func addHypervisorConfigOverrides(ocispec specs.Spec, config *vc.SandboxConfig) error {
Expand Down
26 changes: 20 additions & 6 deletions virtcontainers/pkg/oci/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,12 +666,26 @@ func TestAddAssetAnnotations(t *testing.T) {
assert := assert.New(t)

expectedAnnotations := map[string]string{
vcAnnotations.KernelPath: "/abc/rgb/kernel",
vcAnnotations.ImagePath: "/abc/rgb/image",
vcAnnotations.InitrdPath: "/abc/rgb/initrd",
vcAnnotations.KernelHash: "3l2353we871g",
vcAnnotations.ImageHash: "52ss2550983",
vcAnnotations.AssetHashType: "sha",
vcAnnotations.FirmwarePath: "/some/where",
vcAnnotations.FirmwareHash: "ffff",

vcAnnotations.HypervisorPath: "/some/where",
vcAnnotations.HypervisorHash: "bbbbb",

vcAnnotations.HypervisorCtlPath: "/some/where/else",
vcAnnotations.HypervisorCtlHash: "cc",

vcAnnotations.ImagePath: "/abc/rgb/image",
vcAnnotations.ImageHash: "52ss2550983",

vcAnnotations.InitrdPath: "/abc/rgb/initrd",
vcAnnotations.InitrdHash: "aaaa",

vcAnnotations.JailerPath: "/foo/bar",
vcAnnotations.JailerHash: "dddd",

vcAnnotations.KernelPath: "/abc/rgb/kernel",
vcAnnotations.KernelHash: "3l2353we871g",
}

config := vc.SandboxConfig{
Expand Down
29 changes: 11 additions & 18 deletions virtcontainers/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,31 +419,24 @@ func createAssets(ctx context.Context, sandboxConfig *SandboxConfig) error {
span, _ := trace(ctx, "createAssets")
defer span.Finish()

kernel, err := types.NewAsset(sandboxConfig.Annotations, types.KernelAsset)
if err != nil {
return err
}
for _, name := range types.AssetTypes() {
a, err := types.NewAsset(sandboxConfig.Annotations, name)
if err != nil {
return err
}

image, err := types.NewAsset(sandboxConfig.Annotations, types.ImageAsset)
if err != nil {
return err
if err := sandboxConfig.HypervisorConfig.addCustomAsset(a); err != nil {
return err
}
}

initrd, err := types.NewAsset(sandboxConfig.Annotations, types.InitrdAsset)
if err != nil {
return err
}
_, imageErr := sandboxConfig.HypervisorConfig.assetPath(types.ImageAsset)
_, initrdErr := sandboxConfig.HypervisorConfig.assetPath(types.InitrdAsset)

if image != nil && initrd != nil {
if imageErr != nil && initrdErr != nil {
return fmt.Errorf("%s and %s cannot be both set", types.ImageAsset, types.InitrdAsset)
}

for _, a := range []*types.Asset{kernel, image, initrd} {
if err := sandboxConfig.HypervisorConfig.addCustomAsset(a); err != nil {
return err
}
}

return nil
}

Expand Down
122 changes: 99 additions & 23 deletions virtcontainers/sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,51 +643,127 @@ var assetContentWrongHash = "92549f8d2018a95a294d28a65e795ed7d1a9d150009a28cea10
func TestSandboxCreateAssets(t *testing.T) {
assert := assert.New(t)

type testData struct {
assetType types.AssetType
annotations map[string]string
}

tmpfile, err := ioutil.TempFile("", "virtcontainers-test-")
assert.Nil(err)

filename := tmpfile.Name()

defer func() {
tmpfile.Close()
os.Remove(tmpfile.Name()) // clean up
os.Remove(filename) // clean up
}()

_, err = tmpfile.Write(assetContent)
assert.Nil(err)

originalKernelPath := filepath.Join(testDir, testKernel)
originalImagePath := filepath.Join(testDir, testImage)
originalInitrdPath := filepath.Join(testDir, testInitrd)
originalFirmwarePath := filepath.Join(testDir, testFirmware)
originalHypervisorPath := filepath.Join(testDir, testHypervisor)
originalHypervisorCtlPath := filepath.Join(testDir, testHypervisorCtl)
originalJailerPath := filepath.Join(testDir, testJailer)

hc := HypervisorConfig{
KernelPath: originalKernelPath,
ImagePath: filepath.Join(testDir, testImage),
KernelPath: originalKernelPath,
ImagePath: originalImagePath,
InitrdPath: originalInitrdPath,
FirmwarePath: originalFirmwarePath,
HypervisorPath: originalHypervisorPath,
HypervisorCtlPath: originalHypervisorCtlPath,
JailerPath: originalJailerPath,
}

p := &SandboxConfig{
Annotations: map[string]string{
annotations.KernelPath: tmpfile.Name(),
annotations.KernelHash: assetContentHash,
data := []testData{
{
types.FirmwareAsset,
map[string]string{
annotations.FirmwarePath: filename,
annotations.FirmwareHash: assetContentHash,
},
},
{
types.HypervisorAsset,
map[string]string{
annotations.HypervisorPath: filename,
annotations.HypervisorHash: assetContentHash,
},
},
{
types.HypervisorCtlAsset,
map[string]string{
annotations.HypervisorCtlPath: filename,
annotations.HypervisorCtlHash: assetContentHash,
},
},
{
types.ImageAsset,
map[string]string{
annotations.ImagePath: filename,
annotations.ImageHash: assetContentHash,
},
},
{
types.InitrdAsset,
map[string]string{
annotations.InitrdPath: filename,
annotations.InitrdHash: assetContentHash,
},
},
{
types.JailerAsset,
map[string]string{
annotations.JailerPath: filename,
annotations.JailerHash: assetContentHash,
},
},
{
types.KernelAsset,
map[string]string{
annotations.KernelPath: filename,
annotations.KernelHash: assetContentHash,
},
},

HypervisorConfig: hc,
}

err = createAssets(context.Background(), p)
assert.Nil(err)
for i, d := range data {
msg := fmt.Sprintf("test[%d]: %+v", i, d)

a, ok := p.HypervisorConfig.customAssets[types.KernelAsset]
assert.True(ok)
assert.Equal(a.Path(), tmpfile.Name())
config := &SandboxConfig{
Annotations: d.annotations,
HypervisorConfig: hc,
}

p = &SandboxConfig{
Annotations: map[string]string{
annotations.KernelPath: tmpfile.Name(),
annotations.KernelHash: assetContentWrongHash,
},
err = createAssets(context.Background(), config)
assert.NoError(err, msg)

HypervisorConfig: hc,
}
a, ok := config.HypervisorConfig.customAssets[d.assetType]
assert.True(ok, msg)
assert.Equal(a.Path(), filename, msg)

// Now test with invalid hashes
badHashAnnotations := make(map[string]string)
for k, v := range d.annotations {
if strings.HasSuffix(k, "_hash") {
badHashAnnotations[k] = assetContentWrongHash
} else {
badHashAnnotations[k] = v
}
}

config = &SandboxConfig{
Annotations: badHashAnnotations,
HypervisorConfig: hc,
}

err = createAssets(context.Background(), p)
assert.NotNil(err)
err = createAssets(context.Background(), config)
assert.Error(err, msg)
}
}

func testFindContainerFailure(t *testing.T, sandbox *Sandbox, cid string) {
Expand Down
Loading

0 comments on commit 6a5eb0d

Please sign in to comment.