pipelines: add Fedora IoT commit and container pipelines
This commit is contained in:
parent
1243f84cb0
commit
0f015801d7
5 changed files with 225 additions and 102 deletions
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"math/rand"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
||||
"github.com/osbuild/osbuild-composer/internal/disk"
|
||||
|
|
@ -44,17 +43,6 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
|
|||
return pipelines, nil
|
||||
}
|
||||
|
||||
func prependKernelCmdlineStage(pipeline *osbuild.Pipeline, kernelOptions string, pt *disk.PartitionTable) *osbuild.Pipeline {
|
||||
rootFs := pt.FindMountable("/")
|
||||
if rootFs == nil {
|
||||
panic("root filesystem must be defined for kernel-cmdline stage, this is a programming error")
|
||||
}
|
||||
rootFsUUID := rootFs.GetFSSpec().UUID
|
||||
kernelStage := osbuild.NewKernelCmdlineStage(osbuild.NewKernelCmdlineStageOptions(rootFsUUID, kernelOptions))
|
||||
pipeline.Stages = append([]*osbuild.Stage{kernelStage}, pipeline.Stages...)
|
||||
return pipeline
|
||||
}
|
||||
|
||||
func vhdPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
|
||||
|
|
@ -210,50 +198,46 @@ func iotInstallerPipelines(t *imageType, customizations *blueprint.Customization
|
|||
return pipelines, nil
|
||||
}
|
||||
|
||||
func iotCorePipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec) ([]osbuild.Pipeline, error) {
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
|
||||
func iotCorePipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec) (*pipeline.BuildPipeline, *pipeline.OSPipeline, *pipeline.OSTreeCommitPipeline, error) {
|
||||
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
|
||||
buildPipeline.Repos = repos
|
||||
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
|
||||
pipelines = append(pipelines, buildPipeline.Serialize())
|
||||
|
||||
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
commitPipeline := ostreeCommitPipeline(&buildPipeline, &treePipeline, options, t.arch.distro.osVersion)
|
||||
|
||||
pipelines = append(pipelines, treePipeline.Serialize())
|
||||
|
||||
pipelines = append(pipelines, *ostreeCommitPipeline(options, t.arch.distro.osVersion))
|
||||
|
||||
return pipelines, nil
|
||||
return &buildPipeline, &treePipeline, &commitPipeline, nil
|
||||
}
|
||||
|
||||
func iotCommitPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines, err := iotCorePipelines(t, customizations, options, repos, packageSetSpecs)
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
|
||||
buildPipeline, treePipeline, commitPipeline, err := iotCorePipelines(t, customizations, options, repos, packageSetSpecs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tarPipeline := osbuild.Pipeline{
|
||||
Name: "commit-archive",
|
||||
Build: "name:build",
|
||||
}
|
||||
tarPipeline.AddStage(tarStage("ostree-commit", t.Filename()))
|
||||
pipelines = append(pipelines, tarPipeline)
|
||||
tarPipeline := pipeline.NewTarPipeline(buildPipeline, &commitPipeline.Pipeline, "commit-archive")
|
||||
tarPipeline.Filename = t.Filename()
|
||||
pipelines = append(pipelines, buildPipeline.Serialize(), treePipeline.Serialize(), commitPipeline.Serialize(), tarPipeline.Serialize())
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func iotContainerPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines, err := iotCorePipelines(t, customizations, options, repos, packageSetSpecs)
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
|
||||
buildPipeline, treePipeline, commitPipeline, err := iotCorePipelines(t, customizations, options, repos, packageSetSpecs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nginxConfigPath := "/etc/nginx.conf"
|
||||
httpPort := "8080"
|
||||
pipelines = append(pipelines, *containerTreePipeline(repos, packageSetSpecs[containerPkgsKey], options, customizations, nginxConfigPath, httpPort))
|
||||
pipelines = append(pipelines, *containerPipeline(t, nginxConfigPath, httpPort))
|
||||
containerTreePipeline := containerTreePipeline(buildPipeline, commitPipeline, repos, packageSetSpecs[containerPkgsKey], options, customizations, nginxConfigPath, httpPort)
|
||||
containerPipeline := containerPipeline(buildPipeline, &containerTreePipeline.Pipeline, t, nginxConfigPath, httpPort)
|
||||
|
||||
pipelines = append(pipelines, buildPipeline.Serialize(), treePipeline.Serialize(), commitPipeline.Serialize(), containerTreePipeline.Serialize(), containerPipeline.Serialize())
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
|
|
@ -370,84 +354,33 @@ func osPipeline(buildPipeline *pipeline.BuildPipeline,
|
|||
return pl, nil
|
||||
}
|
||||
|
||||
func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "ostree-commit"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: "/repo"}))
|
||||
|
||||
commitStageInput := new(osbuild.OSTreeCommitStageInput)
|
||||
commitStageInput.Type = "org.osbuild.tree"
|
||||
commitStageInput.Origin = "org.osbuild.pipeline"
|
||||
commitStageInput.References = osbuild.OSTreeCommitStageReferences{"name:ostree-tree"}
|
||||
|
||||
p.AddStage(osbuild.NewOSTreeCommitStage(
|
||||
&osbuild.OSTreeCommitStageOptions{
|
||||
Ref: options.OSTree.Ref,
|
||||
OSVersion: osVersion,
|
||||
Parent: options.OSTree.Parent,
|
||||
},
|
||||
&osbuild.OSTreeCommitStageInputs{Tree: commitStageInput}),
|
||||
)
|
||||
func ostreeCommitPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.OSPipeline, options distro.ImageOptions, osVersion string) pipeline.OSTreeCommitPipeline {
|
||||
p := pipeline.NewOSTreeCommitPipeline(buildPipeline, treePipeline)
|
||||
p.Ref = options.OSTree.Ref
|
||||
p.OSVersion = osVersion
|
||||
p.Parent = options.OSTree.Parent
|
||||
return p
|
||||
}
|
||||
|
||||
func tarStage(source, filename string) *osbuild.Stage {
|
||||
tree := new(osbuild.TarStageInput)
|
||||
tree.Type = "org.osbuild.tree"
|
||||
tree.Origin = "org.osbuild.pipeline"
|
||||
tree.References = []string{"name:" + source}
|
||||
return osbuild.NewTarStage(&osbuild.TarStageOptions{Filename: filename}, &osbuild.TarStageInputs{Tree: tree})
|
||||
}
|
||||
|
||||
func containerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, options distro.ImageOptions, c *blueprint.Customizations, nginxConfigPath, listenPort string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "container-tree"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewRPMStage(osbuild.NewRPMStageOptions(repos), osbuild.NewRpmStageSourceFilesInputs(packages)))
|
||||
func containerTreePipeline(buildPipeline *pipeline.BuildPipeline, commitPipeline *pipeline.OSTreeCommitPipeline, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, options distro.ImageOptions, c *blueprint.Customizations, nginxConfigPath, listenPort string) pipeline.OSTreeCommitServerTreePipeline {
|
||||
p := pipeline.NewOSTreeCommitServerTreePipeline(buildPipeline, commitPipeline)
|
||||
p.Repos = repos
|
||||
p.PackageSpecs = packages
|
||||
p.NginxConfigPath = nginxConfigPath
|
||||
p.ListenPort = listenPort
|
||||
language, _ := c.GetPrimaryLocale()
|
||||
if language != nil {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US"}))
|
||||
p.Language = *language
|
||||
}
|
||||
|
||||
htmlRoot := "/usr/share/nginx/html"
|
||||
repoPath := filepath.Join(htmlRoot, "repo")
|
||||
p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: repoPath}))
|
||||
|
||||
p.AddStage(osbuild.NewOSTreePullStage(
|
||||
&osbuild.OSTreePullStageOptions{Repo: repoPath},
|
||||
osbuild.NewOstreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.Ref),
|
||||
))
|
||||
|
||||
// make nginx log and lib directories world writeable, otherwise nginx can't start in
|
||||
// an unprivileged container
|
||||
p.AddStage(osbuild.NewChmodStage(chmodStageOptions("/var/log/nginx", "a+rwX", true)))
|
||||
p.AddStage(osbuild.NewChmodStage(chmodStageOptions("/var/lib/nginx", "a+rwX", true)))
|
||||
|
||||
p.AddStage(osbuild.NewNginxConfigStage(nginxConfigStageOptions(nginxConfigPath, htmlRoot, listenPort)))
|
||||
return p
|
||||
}
|
||||
|
||||
func containerPipeline(t *imageType, nginxConfigPath, listenPort string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "container"
|
||||
p.Build = "name:build"
|
||||
options := &osbuild.OCIArchiveStageOptions{
|
||||
Architecture: t.Arch().Name(),
|
||||
Filename: t.Filename(),
|
||||
Config: &osbuild.OCIArchiveConfig{
|
||||
Cmd: []string{"nginx", "-c", nginxConfigPath},
|
||||
ExposedPorts: []string{listenPort},
|
||||
},
|
||||
}
|
||||
baseInput := new(osbuild.OCIArchiveStageInput)
|
||||
baseInput.Type = "org.osbuild.tree"
|
||||
baseInput.Origin = "org.osbuild.pipeline"
|
||||
baseInput.References = []string{"name:container-tree"}
|
||||
inputs := &osbuild.OCIArchiveStageInputs{Base: baseInput}
|
||||
p.AddStage(osbuild.NewOCIArchiveStage(options, inputs))
|
||||
func containerPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.Pipeline, t *imageType, nginxConfigPath, listenPort string) pipeline.OCIContainerPipeline {
|
||||
p := pipeline.NewOCIContainerPipeline(buildPipeline, treePipeline)
|
||||
p.Architecture = t.Arch().Name()
|
||||
p.Filename = t.Filename()
|
||||
p.Cmd = []string{"nginx", "-c", nginxConfigPath}
|
||||
p.ExposedPorts = []string{listenPort}
|
||||
return p
|
||||
}
|
||||
|
||||
|
|
|
|||
42
internal/distro/pipelines/commit.go
Normal file
42
internal/distro/pipelines/commit.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
)
|
||||
|
||||
type OSTreeCommitPipeline struct {
|
||||
Pipeline
|
||||
treePipeline *OSPipeline
|
||||
Ref string
|
||||
OSVersion string
|
||||
Parent string
|
||||
}
|
||||
|
||||
func NewOSTreeCommitPipeline(buildPipeline *BuildPipeline, treePipeline *OSPipeline) OSTreeCommitPipeline {
|
||||
return OSTreeCommitPipeline{
|
||||
Pipeline: New("ostree-commit", &buildPipeline.Pipeline),
|
||||
treePipeline: treePipeline,
|
||||
}
|
||||
}
|
||||
|
||||
func (p OSTreeCommitPipeline) Serialize() osbuild2.Pipeline {
|
||||
pipeline := p.Pipeline.Serialize()
|
||||
|
||||
pipeline.AddStage(osbuild2.NewOSTreeInitStage(&osbuild2.OSTreeInitStageOptions{Path: "/repo"}))
|
||||
|
||||
commitStageInput := new(osbuild2.OSTreeCommitStageInput)
|
||||
commitStageInput.Type = "org.osbuild.tree"
|
||||
commitStageInput.Origin = "org.osbuild.pipeline"
|
||||
commitStageInput.References = osbuild2.OSTreeCommitStageReferences{"name:" + p.treePipeline.Name()}
|
||||
|
||||
pipeline.AddStage(osbuild2.NewOSTreeCommitStage(
|
||||
&osbuild2.OSTreeCommitStageOptions{
|
||||
Ref: p.Ref,
|
||||
OSVersion: p.OSVersion,
|
||||
Parent: p.Parent,
|
||||
},
|
||||
&osbuild2.OSTreeCommitStageInputs{Tree: commitStageInput}),
|
||||
)
|
||||
|
||||
return pipeline
|
||||
}
|
||||
74
internal/distro/pipelines/commit_server_tree.go
Normal file
74
internal/distro/pipelines/commit_server_tree.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
type OSTreeCommitServerTreePipeline struct {
|
||||
Pipeline
|
||||
commitPipeline *OSTreeCommitPipeline
|
||||
Repos []rpmmd.RepoConfig
|
||||
PackageSpecs []rpmmd.PackageSpec
|
||||
Language string
|
||||
NginxConfigPath string
|
||||
ListenPort string
|
||||
}
|
||||
|
||||
func NewOSTreeCommitServerTreePipeline(buildPipeline *BuildPipeline, commitPipeline *OSTreeCommitPipeline) OSTreeCommitServerTreePipeline {
|
||||
return OSTreeCommitServerTreePipeline{
|
||||
Pipeline: New("container-tree", &buildPipeline.Pipeline),
|
||||
commitPipeline: commitPipeline,
|
||||
Language: "en_US",
|
||||
}
|
||||
}
|
||||
|
||||
func (p OSTreeCommitServerTreePipeline) Serialize() osbuild2.Pipeline {
|
||||
pipeline := p.Pipeline.Serialize()
|
||||
|
||||
pipeline.AddStage(osbuild2.NewRPMStage(osbuild2.NewRPMStageOptions(p.Repos), osbuild2.NewRpmStageSourceFilesInputs(p.PackageSpecs)))
|
||||
pipeline.AddStage(osbuild2.NewLocaleStage(&osbuild2.LocaleStageOptions{Language: p.Language}))
|
||||
|
||||
htmlRoot := "/usr/share/nginx/html"
|
||||
repoPath := filepath.Join(htmlRoot, "repo")
|
||||
pipeline.AddStage(osbuild2.NewOSTreeInitStage(&osbuild2.OSTreeInitStageOptions{Path: repoPath}))
|
||||
|
||||
pipeline.AddStage(osbuild2.NewOSTreePullStage(
|
||||
&osbuild2.OSTreePullStageOptions{Repo: repoPath},
|
||||
osbuild2.NewOstreePullStageInputs("org.osbuild.pipeline", "name:"+p.commitPipeline.Name(), p.commitPipeline.Ref),
|
||||
))
|
||||
|
||||
// make nginx log and lib directories world writeable, otherwise nginx can't start in
|
||||
// an unprivileged container
|
||||
pipeline.AddStage(osbuild2.NewChmodStage(chmodStageOptions("/var/log/nginx", "a+rwX", true)))
|
||||
pipeline.AddStage(osbuild2.NewChmodStage(chmodStageOptions("/var/lib/nginx", "a+rwX", true)))
|
||||
|
||||
pipeline.AddStage(osbuild2.NewNginxConfigStage(nginxConfigStageOptions(p.NginxConfigPath, htmlRoot, p.ListenPort)))
|
||||
|
||||
return pipeline
|
||||
}
|
||||
|
||||
func nginxConfigStageOptions(path, htmlRoot, listen string) *osbuild2.NginxConfigStageOptions {
|
||||
// configure nginx to work in an unprivileged container
|
||||
cfg := &osbuild2.NginxConfig{
|
||||
Listen: listen,
|
||||
Root: htmlRoot,
|
||||
Daemon: common.BoolToPtr(false),
|
||||
PID: "/tmp/nginx.pid",
|
||||
}
|
||||
return &osbuild2.NginxConfigStageOptions{
|
||||
Path: path,
|
||||
Config: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func chmodStageOptions(path, mode string, recursive bool) *osbuild2.ChmodStageOptions {
|
||||
return &osbuild2.ChmodStageOptions{
|
||||
Items: map[string]osbuild2.ChmodStagePathOptions{
|
||||
path: {Mode: mode, Recursive: recursive},
|
||||
},
|
||||
}
|
||||
}
|
||||
42
internal/distro/pipelines/oci_container.go
Normal file
42
internal/distro/pipelines/oci_container.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
)
|
||||
|
||||
type OCIContainerPipeline struct {
|
||||
Pipeline
|
||||
treePipeline *Pipeline
|
||||
Architecture string
|
||||
Filename string
|
||||
Cmd []string
|
||||
ExposedPorts []string
|
||||
}
|
||||
|
||||
func NewOCIContainerPipeline(buildPipeline *BuildPipeline, treePipeline *Pipeline) OCIContainerPipeline {
|
||||
return OCIContainerPipeline{
|
||||
Pipeline: New("container", &buildPipeline.Pipeline),
|
||||
treePipeline: treePipeline,
|
||||
}
|
||||
}
|
||||
|
||||
func (p OCIContainerPipeline) Serialize() osbuild2.Pipeline {
|
||||
pipeline := p.Pipeline.Serialize()
|
||||
|
||||
options := &osbuild2.OCIArchiveStageOptions{
|
||||
Architecture: p.Architecture,
|
||||
Filename: p.Filename,
|
||||
Config: &osbuild2.OCIArchiveConfig{
|
||||
Cmd: p.Cmd,
|
||||
ExposedPorts: p.ExposedPorts,
|
||||
},
|
||||
}
|
||||
baseInput := new(osbuild2.OCIArchiveStageInput)
|
||||
baseInput.Type = "org.osbuild.tree"
|
||||
baseInput.Origin = "org.osbuild.pipeline"
|
||||
baseInput.References = []string{"name:" + p.treePipeline.Name()}
|
||||
inputs := &osbuild2.OCIArchiveStageInputs{Base: baseInput}
|
||||
pipeline.AddStage(osbuild2.NewOCIArchiveStage(options, inputs))
|
||||
|
||||
return pipeline
|
||||
}
|
||||
32
internal/distro/pipelines/tar.go
Normal file
32
internal/distro/pipelines/tar.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
)
|
||||
|
||||
type TarPipeline struct {
|
||||
Pipeline
|
||||
inputPipeline *Pipeline
|
||||
Filename string
|
||||
}
|
||||
|
||||
func NewTarPipeline(buildPipeline *BuildPipeline, inputPipeline *Pipeline, name string) TarPipeline {
|
||||
return TarPipeline{
|
||||
Pipeline: New(name, &buildPipeline.Pipeline),
|
||||
inputPipeline: inputPipeline,
|
||||
}
|
||||
}
|
||||
|
||||
func (p TarPipeline) Serialize() osbuild2.Pipeline {
|
||||
pipeline := p.Pipeline.Serialize()
|
||||
|
||||
tree := new(osbuild2.TarStageInput)
|
||||
tree.Type = "org.osbuild.tree"
|
||||
tree.Origin = "org.osbuild.pipeline"
|
||||
tree.References = []string{"name:" + p.inputPipeline.Name()}
|
||||
tarStage := osbuild2.NewTarStage(&osbuild2.TarStageOptions{Filename: p.Filename}, &osbuild2.TarStageInputs{Tree: tree})
|
||||
|
||||
pipeline.AddStage(tarStage)
|
||||
|
||||
return pipeline
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue