Build ephemeral iso using generic container
We build iso image in two steps
1) We prepare cloud-init data using a krm function
krm-functions/cloud-init which uses arishipctl capabilities
to gather necessary data from the executor document bundle.
Cloud-init data files are written into a directory mounted
to the krm function container.
2) We build iso image using image-builder. While doing this
we mount the directory with cloud-init data files and set
necessary environment variables defined in the executor
document.
Relates-To: #440
Change-Id: Id0b34822e95f494d2e2f8fb407700b7f873e7c69
This commit is contained in:
11
krm-functions/cloud-init/Dockerfile.sample
Normal file
11
krm-functions/cloud-init/Dockerfile.sample
Normal file
@@ -0,0 +1,11 @@
|
||||
FROM gcr.io/gcp-runtimes/go1-builder:1.13 as builder
|
||||
ENV CGO_ENABLED=0
|
||||
WORKDIR /go/src/
|
||||
COPY image/go.mod .
|
||||
RUN /usr/local/go/bin/go mod download
|
||||
COPY main.go .
|
||||
RUN /usr/local/go/bin/go build -v -o /usr/local/bin/config-function ./
|
||||
|
||||
FROM alpine:latest
|
||||
COPY --from=builder /usr/local/bin/config-function /usr/local/bin/config-function
|
||||
CMD ["/usr/local/bin/config-function"]
|
||||
78
krm-functions/cloud-init/Makefile
Normal file
78
krm-functions/cloud-init/Makefile
Normal file
@@ -0,0 +1,78 @@
|
||||
.PHONY: generate license fix vet fmt test build tidy image
|
||||
|
||||
SHELL := /bin/bash
|
||||
GOBIN := $(shell go env GOPATH)/bin
|
||||
|
||||
# docker image options
|
||||
DOCKER_REGISTRY ?= quay.io
|
||||
DOCKER_IMAGE_NAME ?= cloud-init
|
||||
DOCKER_IMAGE_PREFIX ?= airshipit
|
||||
DOCKER_IMAGE_TAG ?= latest
|
||||
DOCKER_IMAGE ?= $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)
|
||||
PUBLISH ?= false
|
||||
DOCKER_FORCE_CLEAN ?= true
|
||||
|
||||
# proxy options
|
||||
PROXY ?= http://proxy.foo.com:8000
|
||||
NO_PROXY ?= localhost,127.0.0.1,.svc.cluster.local
|
||||
USE_PROXY ?= false
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
(cd image && go build -v -o $(GOBIN)/config-function .)
|
||||
|
||||
.PHONY: all
|
||||
all: generate license build fix vet fmt test lint tidy
|
||||
|
||||
.PHONY: fix
|
||||
fix:
|
||||
(cd image && go fix ./...)
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
(cd image && go fmt ./...)
|
||||
|
||||
.PHONY: generate
|
||||
generate:
|
||||
(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
|
||||
(cd image && GOBIN=$(GOBIN) go generate ./...)
|
||||
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
(cd image && go mod tidy)
|
||||
|
||||
.PHONY: fix
|
||||
lint:
|
||||
(which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
(cd image && $(GOBIN)/golangci-lint run ./...)
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
(cd image && go test -cover ./...)
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
(cd image && go vet ./...)
|
||||
|
||||
.PHONY: image
|
||||
image:
|
||||
ifeq ($(USE_PROXY), true)
|
||||
cd image && \
|
||||
docker build . --network=host \
|
||||
--build-arg http_proxy=$(PROXY) \
|
||||
--build-arg https_proxy=$(PROXY) \
|
||||
--build-arg HTTP_PROXY=$(PROXY) \
|
||||
--build-arg HTTPS_PROXY=$(PROXY) \
|
||||
--build-arg no_proxy=$(NO_PROXY) \
|
||||
--build-arg NO_PROXY=$(NO_PROXY) \
|
||||
--tag $(DOCKER_IMAGE) \
|
||||
--force-rm=$(DOCKER_FORCE_CLEAN)
|
||||
else
|
||||
cd image && \
|
||||
docker build . --network=host \
|
||||
--tag $(DOCKER_IMAGE) \
|
||||
--force-rm=$(DOCKER_FORCE_CLEAN)
|
||||
endif
|
||||
ifeq ($(PUBLISH), true)
|
||||
@docker push $(DOCKER_IMAGE)
|
||||
endif
|
||||
6
krm-functions/cloud-init/README.md
Normal file
6
krm-functions/cloud-init/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Cloud-init
|
||||
|
||||
This function generates yaml files (user-data and network-data) needed for building the bootstrap ISO image.
|
||||
It assumes a `ResourceList` is passed to its input where `items` field is a phase executor document bundle
|
||||
that contains necessary data. To get the data from the bundle the `functionConfig` field must contain
|
||||
`IsoConfiguration` document that defines document selector parameters.
|
||||
9
krm-functions/cloud-init/image/go.mod
Normal file
9
krm-functions/cloud-init/image/go.mod
Normal file
@@ -0,0 +1,9 @@
|
||||
module opendev.org/airship/airshipctl/functions/cloud-init/image
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
opendev.org/airship/airshipctl v0.0.0-20210217205206-b8a4b6ad734c
|
||||
sigs.k8s.io/kustomize/kyaml v0.10.0
|
||||
sigs.k8s.io/kustomize/api v0.7.2
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
apiVersion: config.kubernetes.io/v1alpha1
|
||||
kind: ResourceList
|
||||
items: []
|
||||
functionConfig:
|
||||
apiVersion: airshipit.org/v1alpha1
|
||||
kind: IsoConfiguration
|
||||
metadata:
|
||||
annotations:
|
||||
config.kubernetes.io/function: |-
|
||||
container:
|
||||
image: krm-function-cloud-init:latest
|
||||
name: cloud-init
|
||||
builder:
|
||||
userDataSelector:
|
||||
kind: Secret
|
||||
labelSelector: airshipit.org/ephemeral-user-data
|
||||
userDataKey: userData
|
||||
networkConfigSelector:
|
||||
kind: BareMetalHost
|
||||
labelSelector: airshipit.org/ephemeral-node
|
||||
networkConfigKey: networkData
|
||||
128
krm-functions/cloud-init/main.go
Normal file
128
krm-functions/cloud-init/main.go
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/kyaml/fn/framework"
|
||||
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/api/v1alpha1"
|
||||
"opendev.org/airship/airshipctl/pkg/bootstrap/cloudinit"
|
||||
"opendev.org/airship/airshipctl/pkg/document"
|
||||
"opendev.org/airship/airshipctl/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
builderConfigFileName = "builder-conf.yaml"
|
||||
userDataFileName = "user-data"
|
||||
networkConfigFileName = "network-data"
|
||||
)
|
||||
|
||||
func bundleFromRNodes(rnodes []*yaml.RNode) (document.Bundle, error) {
|
||||
p := provider.NewDefaultDepProvider()
|
||||
resmapFactory := resmap.NewFactory(p.GetResourceFactory(), p.GetConflictDetectorFactory())
|
||||
resmap, err := resmapFactory.NewResMapFromRNodeSlice(rnodes)
|
||||
if err != nil {
|
||||
return &document.BundleFactory{}, err
|
||||
}
|
||||
return &document.BundleFactory{
|
||||
ResMap: resmap,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func docFromRNode(rnode *yaml.RNode) (document.Document, error) {
|
||||
rnodes := []*yaml.RNode{rnode}
|
||||
bundle, err := bundleFromRNodes(rnodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
collection, err := bundle.GetAllDocuments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(collection) == 0 {
|
||||
return nil, errors.New("Error while converting RNode to Document: empty document bundle")
|
||||
}
|
||||
return collection[0], nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
resourceList := &framework.ResourceList{}
|
||||
cmd := framework.Command(resourceList, func() error {
|
||||
functionConfig, ok := resourceList.FunctionConfig.(*yaml.RNode)
|
||||
if !ok {
|
||||
return errors.New("Error while type assert of FunctionConfig")
|
||||
}
|
||||
|
||||
functionConfigDocument, err := docFromRNode(functionConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
functionConfigYaml, err := functionConfigDocument.AsYAML()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isoConfiguration := &v1alpha1.IsoConfiguration{}
|
||||
err = functionConfigDocument.ToAPIObject(isoConfiguration, v1alpha1.Scheme)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
docBundle, err := bundleFromRNodes(resourceList.Items)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userData, netConf, err := cloudinit.GetCloudData(
|
||||
docBundle,
|
||||
isoConfiguration.Isogen.UserDataSelector,
|
||||
isoConfiguration.Isogen.UserDataKey,
|
||||
isoConfiguration.Isogen.NetworkConfigSelector,
|
||||
isoConfiguration.Isogen.NetworkConfigKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
functionSpec := runtimeutil.GetFunctionSpec(functionConfig)
|
||||
configPath := functionSpec.Container.StorageMounts[0].DstPath
|
||||
|
||||
fls := make(map[string][]byte)
|
||||
fls[filepath.Join(configPath, userDataFileName)] = userData
|
||||
fls[filepath.Join(configPath, networkConfigFileName)] = netConf
|
||||
fls[filepath.Join(configPath, builderConfigFileName)] = functionConfigYaml
|
||||
|
||||
if err = util.WriteFiles(fls, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resourceList.Items = []*yaml.RNode{}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user