# Defining Images
Tom Gundersen
Image Builder @ Red Hat
slides: https://bit.ly/3yQAmpd
---
## Building Images
---
## osbuild
- anyone can build images<!-- .element: class="fragment" -->
- we can build the same image twice <!-- .element: class="fragment" -->
- comparable to an assembler - not a compiler<!-- .element: class="fragment" -->
- reproducible<!-- .element: class="fragment" -->
- low-level<!-- .element: class="fragment" -->
- pluggable<!-- .element: class="fragment" -->
- extensible<!-- .element: class="fragment" -->
- policy-less<!-- .element: class="fragment" -->
https://github.com/osbuild/osbuild
----
### manifests
- input to osbuild in JSON format<!-- .element: class="fragment" -->
- defines a set of filesystem trees <!-- .element: class="fragment" -->
- e.g., one tree containing an image<!-- .element: class="fragment" -->
- same manifest produces the same* image<!-- .element: class="fragment" -->
- defined in terms of<!-- .element: class="fragment" -->
- a set of 'sources' and<!-- .element: class="fragment" -->
- a set of 'pipelines'<!-- .element: class="fragment" -->
----
### pipelines
- defines a single filesystem tree<!-- .element: class="fragment" -->
- may consume other trees as input<!-- .element: class="fragment" -->
- defined as a sequence of 'stages'<!-- .element: class="fragment" -->
----
### stages
- defines a modification to a filesystem tree<!-- .element: class="fragment" -->
- declarative<!-- .element: class="fragment" -->
- policy-less<!-- .element: class="fragment" -->
- reproducible<!-- .element: class="fragment" -->
- isolated from the host<!-- .element: class="fragment" -->
- scoped to one tool<!-- .element: class="fragment" -->
- sandboxes and unifies existing tools<!-- .element: class="fragment" -->
----
### example
```json
{
"version": "2",
"pipelines": [
{
"name": "os",
"stages": [
{
"type": "org.osbuild.rpm",
...
},
...
]
},
...
]
}
```
---
## Defining Images
---
## osbuild-composer
- uniformly define all the images<!-- .element: class="fragment" -->
- one services to build everything for everyone everywhere<!-- .element: class="fragment" -->
- distros:<!-- .element: class="fragment" -->
- Fedora, CentOS Stream, RHEL<!-- .element: class="fragment" -->
- footprints:<!-- .element: class="fragment" -->
- Bare metal, Cloud, Virt, Edge<!-- .element: class="fragment" -->
- architectures:<!-- .element: class="fragment" -->
- x86_64, aarch64, ppc64le, s390x<!-- .element: class="fragment" -->
- available: on-prem, hosted, soon through koji<!-- .element: class="fragment" -->
https://github.com/osbuild/osbuild-composer
----
### Public API
- stable<!-- .element: class="fragment" -->
- very high-level<!-- .element: class="fragment" -->
- all artefacts end-to-end tested<!-- .element: class="fragment" -->
----
### Private API
- unstable<!-- .element: class="fragment" -->
- not end-to-end tested<!-- .element: class="fragment" -->
- declarative<!-- .element: class="fragment" -->
- policy-rich<!-- .element: class="fragment" -->
- reproducible<!-- .element: class="fragment" -->
---
## Image Kind
```go
type ImageKind interface {
InstantiateManifest(m *manifest.Manifest,
...) error
...
}
```
```go
type OSTreeArchive struct {
Platform platform.Platform
OSCustomizations manifest.OSCustomizations
Environment environment.Environment
Workload workload.Workload
OSTreeParent manifest.OSTree
OSTreeRef string
...
}
```
<!-- .element: class="fragment" -->
----
## Manifest
```go
func (m Manifest) GetPackageSetChains()
map[string][]rpmmd.PackageSet
{...}
func (m Manifest) Serialize(
packageSets map[string][]rpmmd.PackageSpec)
([]byte], error)
{...}
```
----
### Pipeline
```go
type Pipeline interface {
Name() string
getBuildPackages() []string
getPackageSetChain() []rpmmd.PackageSet
serialize([]rpmmd.PackageSpec) osbuild2.Pipeline
...
}
```
----
### Build Pipeline
```go
func NewBuild(m *Manifest,
runner runner.Runner,
repos []rpmmd.RepoConfig) *Build
{...}
```
----
### OS Pipeline
```go
func NewOS(m *Manifest,
buildPipeline *Build,
platform platform.Platform,
repos []rpmmd.RepoConfig) *OS
{...}
```
----
### Hardware Platform
```go
type Platform interface {
GetArch() Arch
GetBIOSPlatform() string
GetUEFIVendor() string
GetPackages() []string
GetBuildPackages() []string
...
}
```
```go
type X86 struct {
BasePlatform
BIOS bool
UEFIVendor string
}
```
<!-- .element: class="fragment" -->
```go
type Aarch64 struct {
UEFIVendor string
}
```
<!-- .element: class="fragment" -->
----
### RawImage Pipeline
```go
func NewRawImage(m *Manifest,
buildPipeline *Build,
treePipeline *OS) *RawImage
{...}
```
----
### Customizing Pipelines
```go
type OS struct {
PartitionTable *disk.PartitionTable
Environment environment.Environment
Workload workload.Workload
...
}
```
----
### Environment
```go
type Environment interface {
GetPackages() []string
GetServices() []string
}
```
```go
type Azure struct {...}
func (p *Azure) GetPackages() []string {
return []string{"WALinuxAgent"}
}
func (p *Azure) GetServices() []string {
return []string{"waagent"}
}
```
<!-- .element: class="fragment" -->
----
### Workload
```go
type Workload interface {
GetPackages() []string
GetServices() []string
...
}
```
```go
type Custom struct {
Packages []string
Services []string
...
}
```
<!-- .element: class="fragment" -->
```go
type MicroShift struct {}
```
<!-- .element: class="fragment" -->
```go
type Anaconda struct {}
```
<!-- .element: class="fragment" -->
---
### Demo! :banana:
```sh
go run ./cmd/osbuild-playground
```
<div style="text-align: right; color: grey; font-size: 0.5em"> using upstream VSCode devcontainer</div>
{"metaMigratedAt":"2023-06-17T04:30:19.511Z","metaMigratedFrom":"YAML","title":"Defining Images","breaks":true,"description":"How images are defined and built with osbuild","slideOptions":"{\"allottedMinutes\":15,\"transition\":\"slide\",\"image\":\"https://www.osbuild.org/images/osbuild.png\"}","contributors":"[{\"id\":\"8f5474a9-6266-468e-9a82-2653e71aaa7b\",\"add\":10028,\"del\":3585}]"}