Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/user/reference/config/config-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ All config files share the same schema — there is no distinction between a "ro
| `components` | map of objects | Component (package) definitions | [Components](components.md) |
| `component-groups` | map of objects | Named groups of components with shared defaults | [Component Groups](component-groups.md) |
| `images` | map of objects | Image definitions (VMs, containers) | [Images](images.md) |
| `test-suites` | map of objects | Named test suite definitions referenced by images | [Test Suites](test-suites.md) |
| `tools` | object | Configuration for external tools used by azldev | [Tools](tools.md) |
| `default-package-config` | object | Project-wide default applied to all binary packages | [Package Groups — Resolution Order](package-groups.md#resolution-order) |
| `package-groups` | map of objects | Named groups of binary packages with shared config | [Package Groups](package-groups.md) |

## Includes

Expand Down
72 changes: 70 additions & 2 deletions docs/user/reference/config/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ The `[images]` section defines system images (VMs, containers, etc.) that azldev
|-------|----------|------|----------|-------------|
| Description | `description` | string | No | Human-readable description of the image |
| Definition | `definition` | [ImageDefinition](#image-definition) | No | Specifies the image definition format, file path, and optional profile |
| Capabilities | `capabilities` | [ImageCapabilities](#image-capabilities) | No | Describes features and properties of this image |
| Tests | `tests` | [ImageTests](#image-tests) | No | Test configuration for this image |
| Publish | `publish` | [ImagePublish](#image-publish) | No | Publishing settings for this image |

## Image Definition

Expand All @@ -19,24 +22,59 @@ The `definition` field tells azldev where to find the image definition file and
| Path | `path` | string | No | Path to the image definition file, relative to the config file |
| Profile | `profile` | string | No | Build profile to use when building the image (format-specific) |

## Image Capabilities

The `capabilities` subtable describes what the image supports. All fields are optional booleans using tri-state semantics: `true` (explicitly enabled), `false` (explicitly disabled), or omitted (unspecified / inherit from defaults).

| Field | TOML Key | Type | Default | Description |
|-------|----------|------|---------|-------------|
| Machine Bootable | `machine-bootable` | bool | unset | Whether the image can be booted on a machine (bare metal or VM) |
| Container | `container` | bool | unset | Whether the image can be run on an OCI container host |
| Systemd | `systemd` | bool | unset | Whether the image runs systemd as its init system |
| Runtime Package Management | `runtime-package-management` | bool | unset | Whether the image supports installing/removing packages at runtime (e.g., via dnf/tdnf) |

## Image Tests

The `tests` subtable links an image to one or more test suites defined in the top-level [`[test-suites]`](test-suites.md) section.

| Field | TOML Key | Type | Required | Description |
|-------|----------|------|----------|-------------|
| Test Suites | `test-suites` | array of inline tables | No | List of test suite references. Each entry must have a `name` field matching a key in `[test-suites]`. |

## Image Publish

The `publish` subtable configures where an image is published. Unlike packages (which target a single channel), images may be published to multiple channels simultaneously.

| Field | TOML Key | Type | Required | Description |
|-------|----------|------|----------|-------------|
| Channels | `channels` | string array | No | List of publish channels for this image |

> **Note:** Each image name must be unique across all config files. Defining the same image name in two files produces an error.

## Examples

### VM image using Kiwi
### VM image with capabilities

```toml
[images.vm-base]
description = "VM Base Image"
definition = { type = "kiwi", path = "vm-base/vm-base.kiwi" }

[images.vm-base.capabilities]
machine-bootable = true
systemd = true
runtime-package-management = true
```

### Container image
### Container image with capabilities

```toml
[images.container-base]
description = "Container Base Image"
definition = { type = "kiwi", path = "container-base/container-base.kiwi" }

[images.container-base.capabilities]
container = true
```

### Image with a build profile
Expand All @@ -47,7 +85,37 @@ description = "Azure-optimized VM image"
definition = { type = "kiwi", path = "vm-azure/vm-azure.kiwi", profile = "azure" }
```

### Image with test suite references

```toml
[images.vm-base]
description = "VM Base Image"
definition = { type = "kiwi", path = "vm-base/vm-base.kiwi" }

[images.vm-base.capabilities]
machine-bootable = true
systemd = true

[images.vm-base.tests]
test-suites = [
{ name = "smoke" },
{ name = "integration" },
]
```

### Image with publish channels

```toml
[images.vm-base]
description = "VM Base Image"
definition = { type = "kiwi", path = "vm-base/vm-base.kiwi" }

[images.vm-base.publish]
channels = ["registry-prod", "registry-staging"]
```

## Related Resources

- [Config File Structure](config-file.md) — top-level config file layout
- [Test Suites](test-suites.md) — test suite definitions
- [Tools](tools.md) — Image Customizer tool configuration
43 changes: 43 additions & 0 deletions docs/user/reference/config/test-suites.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Test Suites

The `[test-suites]` section defines named test suites that can be referenced by images. Each test suite is defined under `[test-suites.<name>]`.

## Test Suite Config

| Field | TOML Key | Type | Required | Description |
|-------|----------|------|----------|-------------|
| Description | `description` | string | No | Human-readable description of the test suite |

Test suites are referenced by images through the [`[images.<name>.tests]`](images.md#image-tests) subtable. Each image can reference one or more test suites by name.

> **Note:** Each test suite name must be unique across all config files. Defining the same test suite name in two files produces an error.

## Examples

### Basic test suite definitions

```toml
[test-suites.smoke]
description = "Smoke tests for basic image validation"

[test-suites.integration]
description = "Integration tests for live VM validation"
```

### Referencing test suites from an image

```toml
[test-suites.smoke]
description = "Smoke tests"

[images.vm-base]
description = "VM Base Image"

[images.vm-base.tests]
test-suites = [{ name = "smoke" }]
```

## Related Resources

- [Images](images.md) — image configuration including test references
- [Config File Structure](config-file.md) — top-level config file layout
32 changes: 30 additions & 2 deletions internal/app/azldev/cmds/image/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"

"github.com/microsoft/azure-linux-dev-tools/internal/app/azldev"
"github.com/microsoft/azure-linux-dev-tools/internal/projectconfig"
"github.com/samber/lo"
"github.com/spf13/cobra"
)
Expand All @@ -28,6 +29,26 @@ type ImageListResult struct {
// Description of the image.
Description string `json:"description"`

// Capabilities describes the features and properties of this image.
Capabilities projectconfig.ImageCapabilities `json:"capabilities" table:"-"`

// CapabilitiesSummary is a comma-separated summary of enabled capabilities for table
// display.
CapabilitiesSummary string `json:"-" table:"Capabilities"`

// Tests holds the test configuration for this image, matching the original config
// structure.
Tests projectconfig.ImageTestsConfig `json:"tests" table:"-"`

// TestsSummary is a comma-separated summary of test suite names for table display.
TestsSummary string `json:"-" table:"Tests"`

// Publish holds the publish settings for this image.
Publish projectconfig.ImagePublishConfig `json:"publish" table:"-"`

// PublishSummary is a comma-separated summary of publish channels for table display.
PublishSummary string `json:"-" table:"Publish"`

// Definition contains the image definition details (hidden from table output).
Definition ImageDefinitionResult `json:"definition" table:"-"`
}
Expand Down Expand Up @@ -108,9 +129,16 @@ func ListImages(env *azldev.Env, options *ListImageOptions) ([]ImageListResult,
}

imageConfig := cfg.Images[name]

results = append(results, ImageListResult{
Name: name,
Description: imageConfig.Description,
Name: name,
Description: imageConfig.Description,
Capabilities: imageConfig.Capabilities,
CapabilitiesSummary: strings.Join(imageConfig.Capabilities.EnabledNames(), ", "),
Tests: imageConfig.Tests,
TestsSummary: strings.Join(imageConfig.TestNames(), ", "),
Publish: imageConfig.Publish,
PublishSummary: strings.Join(imageConfig.Publish.Channels, ", "),
Definition: ImageDefinitionResult{
Type: string(imageConfig.Definition.DefinitionType),
Path: imageConfig.Definition.Path,
Expand Down
86 changes: 86 additions & 0 deletions internal/app/azldev/cmds/image/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/microsoft/azure-linux-dev-tools/internal/app/azldev/cmds/image"
"github.com/microsoft/azure-linux-dev-tools/internal/app/azldev/core/testutils"
"github.com/microsoft/azure-linux-dev-tools/internal/projectconfig"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -78,6 +79,91 @@ func TestListImages_AllImages(t *testing.T) {
assert.Equal(t, "Image B description", results[1].Description)
}

func TestListImages_WithCapabilitiesAndTests(t *testing.T) {
testEnv := testutils.NewTestEnv(t)
testEnv.Config.Images = map[string]projectconfig.ImageConfig{
"vm-base": {
Name: "vm-base",
Description: "VM Base Image",
Capabilities: projectconfig.ImageCapabilities{
MachineBootable: lo.ToPtr(true),
Systemd: lo.ToPtr(true),
},
Tests: projectconfig.ImageTestsConfig{
TestSuites: []projectconfig.TestSuiteRef{
{Name: "smoke"},
{Name: "integration"},
},
},
Publish: projectconfig.ImagePublishConfig{
Channels: []string{"registry-prod", "registry-staging"},
},
},
"container-base": {
Name: "container-base",
Description: "Container Base Image",
Capabilities: projectconfig.ImageCapabilities{
Container: lo.ToPtr(true),
},
Tests: projectconfig.ImageTestsConfig{
TestSuites: []projectconfig.TestSuiteRef{
{Name: "smoke"},
},
},
Publish: projectconfig.ImagePublishConfig{
Channels: []string{"registry-prod"},
},
},
"minimal": {
Name: "minimal",
Description: "Minimal image with no capabilities or tests",
},
}

options := &image.ListImageOptions{}

results, err := image.ListImages(testEnv.Env, options)
require.NoError(t, err)
require.Len(t, results, 3)

// Results sorted alphabetically.
assert.Equal(t, "container-base", results[0].Name)
assert.Equal(t, lo.ToPtr(true), results[0].Capabilities.Container)
assert.Nil(t, results[0].Capabilities.MachineBootable)
assert.Equal(t, "container", results[0].CapabilitiesSummary)
assert.Equal(t, projectconfig.ImageTestsConfig{
TestSuites: []projectconfig.TestSuiteRef{{Name: "smoke"}},
}, results[0].Tests)
assert.Equal(t, "smoke", results[0].TestsSummary)
assert.Equal(t, projectconfig.ImagePublishConfig{
Channels: []string{"registry-prod"},
}, results[0].Publish)
assert.Equal(t, "registry-prod", results[0].PublishSummary)

assert.Equal(t, "minimal", results[1].Name)
assert.Nil(t, results[1].Capabilities.MachineBootable)
assert.Nil(t, results[1].Capabilities.Container)
assert.Empty(t, results[1].CapabilitiesSummary)
assert.Empty(t, results[1].Tests.TestSuites)
assert.Empty(t, results[1].TestsSummary)
assert.Empty(t, results[1].Publish.Channels)
assert.Empty(t, results[1].PublishSummary)

assert.Equal(t, "vm-base", results[2].Name)
assert.Equal(t, lo.ToPtr(true), results[2].Capabilities.MachineBootable)
assert.Equal(t, lo.ToPtr(true), results[2].Capabilities.Systemd)
assert.Nil(t, results[2].Capabilities.Container)
assert.Equal(t, "machine-bootable, systemd", results[2].CapabilitiesSummary)
assert.Equal(t, projectconfig.ImageTestsConfig{
TestSuites: []projectconfig.TestSuiteRef{{Name: "smoke"}, {Name: "integration"}},
}, results[2].Tests)
assert.Equal(t, "smoke, integration", results[2].TestsSummary)
assert.Equal(t, projectconfig.ImagePublishConfig{
Channels: []string{"registry-prod", "registry-staging"},
}, results[2].Publish)
assert.Equal(t, "registry-prod, registry-staging", results[2].PublishSummary)
}

func TestListImages_ExactMatch(t *testing.T) {
testEnv := testutils.NewTestEnv(t)
testEnv.Config.Images = map[string]projectconfig.ImageConfig{
Expand Down
3 changes: 3 additions & 0 deletions internal/projectconfig/configfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type ConfigFile struct {
// to be applied to sets of binary packages.
PackageGroups map[string]PackageGroupConfig `toml:"package-groups,omitempty" validate:"dive" jsonschema:"title=Package groups,description=Definitions of package groups for shared binary package configuration"`

// Definitions of test suites.
TestSuites map[string]TestSuiteConfig `toml:"test-suites,omitempty" validate:"dive" jsonschema:"title=Test Suites,description=Definitions of test suites for this project"`

// Internal fields used to track the origin of the config file; `dir` is the directory
// that the config file's relative paths are based from.
sourcePath string `toml:"-"`
Expand Down
Loading
Loading