mirror of https://github.com/knative/func.git
Optimise func-utils image (#2686)
* Use command instad of script in some tkn tasks The "script" requires /bin/sh present in the image. Signed-off-by: Matej Vašek <mvasek@redhat.com> * Add s2i-generate command to func-util image The command encompasses some logic previously implemented as shell script defined in tekton task. This allows us to remove sh/shell from the func-util image. Signed-off-by: Matej Vašek <mvasek@redhat.com> * Make func-util image "FROM scratch" Signed-off-by: Matej Vašek <mvasek@redhat.com> * Change func-utils image tag latest->v2 Since there are backward incompatible changes we must not change how 'latest' tag work (at least for some time). For this reason we change tag to v2, so newer versions of func use that and older use 'latest' that is compatible with them. Signed-off-by: Matej Vašek <mvasek@redhat.com> --------- Signed-off-by: Matej Vašek <mvasek@redhat.com>
This commit is contained in:
parent
f8db896f85
commit
9c0c216193
|
|
@ -180,6 +180,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: knative/actions/setup-go@main
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
|
|
@ -189,12 +190,14 @@ jobs:
|
|||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
run: |
|
||||
./hack/fetch-util-img-prerequisites.sh
|
||||
for a in amd64 arm64 ppc64le s390x; do
|
||||
CGO_ENABLED=0 go build -o "func-util-$a" -trimpath -ldflags '-w -s' ./cmd/func-util
|
||||
done
|
||||
docker buildx create --name multiarch --driver docker-container --use
|
||||
docker buildx build . -f Dockerfile.utils \
|
||||
--platform=linux/ppc64le,linux/s390x,linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
-t "ghcr.io/knative/func-utils:latest" \
|
||||
-t "ghcr.io/knative/func-utils:v2" \
|
||||
--annotation index:org.opencontainers.image.description="Knative Func Utils Image" \
|
||||
--annotation index:org.opencontainers.image.source="https://github.com/knative/func" \
|
||||
--annotation index:org.opencontainers.image.vendor="https://github.com/knative/func" \
|
||||
|
|
|
|||
|
|
@ -1,41 +1,13 @@
|
|||
FROM --platform=$BUILDPLATFORM scratch AS builder
|
||||
|
||||
ARG BUILDPLATFORM
|
||||
ARG BUILDARCH
|
||||
ARG TARGETPLATFORM
|
||||
ARG TARGETARCH
|
||||
|
||||
ADD .artifacts/alpine-minirootfs-$BUILDARCH.tar.gz /
|
||||
|
||||
COPY .artifacts/go.tar.gz /tmp/go.tar.gz
|
||||
RUN tar -C /usr/local -xzf /tmp/go.tar.gz
|
||||
ENV PATH="/usr/local/go/bin:$PATH"
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download -x
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN GOARCH=$TARGETARCH go build -o func-util -trimpath -ldflags '-w -s' ./cmd/func-util
|
||||
|
||||
#########################
|
||||
|
||||
FROM scratch
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG FUNC_UTIL_BINARY=func-util-$TARGETARCH
|
||||
|
||||
ADD .artifacts/alpine-minirootfs-$TARGETARCH.tar.gz /
|
||||
ENV PATH=/
|
||||
|
||||
RUN apk add --no-cache tar
|
||||
COPY $FUNC_UTIL_BINARY /func-util
|
||||
|
||||
COPY --from=builder /workspace/func-util /usr/local/bin/
|
||||
RUN ln -s /usr/local/bin/func-util /usr/local/bin/deploy && \
|
||||
ln -s /usr/local/bin/func-util /usr/local/bin/scaffold && \
|
||||
ln -s /usr/local/bin/func-util /usr/local/bin/s2i && \
|
||||
ln -s /usr/local/bin/func-util /usr/local/bin/sh && \
|
||||
ln -s /usr/local/bin/func-util /usr/local/bin/socat
|
||||
ADD func-util-symlinks.tgz /
|
||||
|
||||
LABEL \
|
||||
org.opencontainers.image.description="Knative Func Utils Image" \
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -30,7 +30,7 @@ KVER ?= $(shell git describe --tags --match 'knative-*')
|
|||
|
||||
LDFLAGS := -X knative.dev/func/pkg/app.vers=$(VERS) -X knative.dev/func/pkg/app.kver=$(KVER) -X knative.dev/func/pkg/app.hash=$(HASH)
|
||||
|
||||
FUNC_UTILS_IMG ?= ghcr.io/knative/func-utils:latest
|
||||
FUNC_UTILS_IMG ?= ghcr.io/knative/func-utils:v2
|
||||
LDFLAGS += -X knative.dev/func/pkg/k8s.SocatImage=$(FUNC_UTILS_IMG)
|
||||
LDFLAGS += -X knative.dev/func/pkg/k8s.TarImage=$(FUNC_UTILS_IMG)
|
||||
LDFLAGS += -X knative.dev/func/pkg/pipelines/tekton.DeployerImage=$(FUNC_UTILS_IMG)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ func main() {
|
|||
cmd = socat
|
||||
case "sh":
|
||||
cmd = sh
|
||||
case "s2i-generate":
|
||||
cmd = s2iGenerate
|
||||
}
|
||||
|
||||
err := cmd(ctx)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
//go:build exclude_graphdriver_btrfs || !cgo
|
||||
// +build exclude_graphdriver_btrfs !cgo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/openshift/source-to-image/pkg/api"
|
||||
"github.com/openshift/source-to-image/pkg/build"
|
||||
"github.com/openshift/source-to-image/pkg/build/strategies"
|
||||
"github.com/openshift/source-to-image/pkg/scm/git"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "knative.dev/func/pkg/functions"
|
||||
)
|
||||
|
||||
func s2iGenerate(ctx context.Context) error {
|
||||
cmd := newS2IGenerateCmd()
|
||||
err := cmd.ExecuteContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot s2i generate: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type genConfig struct {
|
||||
target string
|
||||
pathContext string
|
||||
builderImage string
|
||||
registry string
|
||||
imageScriptUrl string
|
||||
logLevel string
|
||||
envVars []string
|
||||
}
|
||||
|
||||
func newS2IGenerateCmd() *cobra.Command {
|
||||
var config genConfig
|
||||
|
||||
genCmd := &cobra.Command{
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
config.envVars = args
|
||||
return runS2IGenerate(cmd.Context(), config)
|
||||
},
|
||||
}
|
||||
genCmd.Flags().StringVar(&config.target, "target", "/gen-source", "")
|
||||
genCmd.Flags().StringVar(&config.pathContext, "path-context", ".", "")
|
||||
genCmd.Flags().StringVar(&config.builderImage, "builder-image", "", "")
|
||||
genCmd.Flags().StringVar(&config.registry, "registry", "", "")
|
||||
genCmd.Flags().StringVar(&config.imageScriptUrl, "image-script-url", "image:///usr/libexec/s2i", "")
|
||||
genCmd.Flags().StringVar(&config.logLevel, "log-level", "0", "")
|
||||
|
||||
return genCmd
|
||||
}
|
||||
|
||||
func runS2IGenerate(ctx context.Context, c genConfig) error {
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get working directory: %w", err)
|
||||
}
|
||||
|
||||
funcRoot := filepath.Join(wd, c.pathContext)
|
||||
|
||||
// replace registry in func.yaml
|
||||
f, err := fn.NewFunction(funcRoot)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot load function: %w", err)
|
||||
}
|
||||
f.Registry = c.registry
|
||||
err = f.Write()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot write function: %w", err)
|
||||
}
|
||||
|
||||
// append node_modules into .s2iignore
|
||||
s2iIgnorePath := filepath.Join(funcRoot, ".s2iignore")
|
||||
if fi, _ := os.Stat(s2iIgnorePath); fi != nil {
|
||||
var file *os.File
|
||||
|
||||
file, err = os.OpenFile(s2iIgnorePath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot open s2i ignore file for append: %w", err)
|
||||
}
|
||||
defer func(file *os.File) {
|
||||
_ = file.Close()
|
||||
|
||||
}(file)
|
||||
|
||||
_, err = file.Write([]byte("\nnode_modules"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot append node_modules directory to s2i ignore file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// prepare envvars
|
||||
var envs = make([]api.EnvironmentSpec, 0, len(c.envVars))
|
||||
for _, e := range c.envVars {
|
||||
var es api.EnvironmentSpec
|
||||
part := strings.SplitN(e, "=", 2)
|
||||
switch len(part) {
|
||||
case 1:
|
||||
es.Name = part[0]
|
||||
case 2:
|
||||
es.Name = part[0]
|
||||
es.Value = part[1]
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if es.Name != "" {
|
||||
envs = append(envs, es)
|
||||
}
|
||||
}
|
||||
|
||||
s2iConfig := api.Config{
|
||||
Source: &git.URL{
|
||||
URL: url.URL{Path: funcRoot},
|
||||
Type: git.URLTypeLocal,
|
||||
},
|
||||
BuilderImage: c.builderImage,
|
||||
ImageScriptsURL: c.imageScriptUrl,
|
||||
KeepSymlinks: true,
|
||||
Environment: envs,
|
||||
AsDockerfile: filepath.Join(c.target, "Dockerfile.gen"),
|
||||
}
|
||||
|
||||
builder, _, err := strategies.Strategy(nil, &s2iConfig, build.Overrides{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create builder: %w", err)
|
||||
}
|
||||
|
||||
_, err = builder.Build(&s2iConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot build: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Binary file not shown.
|
|
@ -1,60 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
alpine_version='3.21.2'
|
||||
go_version='1.23.5'
|
||||
|
||||
alpine_release_key='0482D84022F52DF1C4E7CD43293ACD0907D9495A'
|
||||
google_release_key='EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796'
|
||||
|
||||
artifacts_dir="$(dirname "$(realpath "$0")")/../.artifacts"
|
||||
if [ ! -d "$artifacts_dir" ]; then
|
||||
mkdir "$artifacts_dir";
|
||||
fi
|
||||
|
||||
GNUPGHOME="$(mktemp -d)"
|
||||
export GNUPGHOME
|
||||
gpg --keyserver 'keyserver.ubuntu.com' --recv-keys "$alpine_release_key"
|
||||
gpg --keyserver 'keyserver.ubuntu.com' --recv-keys "$google_release_key"
|
||||
|
||||
declare -A arch_map
|
||||
arch_map['x86_64']='amd64'
|
||||
arch_map['aarch64']='arm64'
|
||||
|
||||
function fetch_alpine_minirootfs() {
|
||||
local alpine_rel_url='https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases'
|
||||
|
||||
local arch
|
||||
for arch in 'x86_64' 'aarch64' 'ppc64le' 's390x'; do
|
||||
local arch_alt="${arch_map[$arch]:-$arch}"
|
||||
local tarball="${artifacts_dir}/alpine-minirootfs-${arch_alt}.tar.gz"
|
||||
local signature="${artifacts_dir}/alpine-minirootfs-${arch_alt}.tar.gz.asc"
|
||||
curl -sSL "${alpine_rel_url}/${arch}/alpine-minirootfs-${alpine_version}-${arch}.tar.gz" > \
|
||||
"${tarball}"
|
||||
curl -sSL "${alpine_rel_url}/${arch}/alpine-minirootfs-${alpine_version}-${arch}.tar.gz.asc" > \
|
||||
"${signature}"
|
||||
gpg --assert-signer="$alpine_release_key" --verify "${signature}" "${tarball}"
|
||||
done
|
||||
}
|
||||
|
||||
function fetch_golang() {
|
||||
|
||||
local arch
|
||||
arch="$(uname -m)"
|
||||
local arch_alt="${arch_map[$arch]:-$arch}"
|
||||
local tarball="${artifacts_dir}/go.tar.gz"
|
||||
local signature="${artifacts_dir}/go.tar.gz.asc"
|
||||
curl -sSL "https://go.dev/dl/go${go_version}.linux-${arch_alt}.tar.gz" > "${tarball}"
|
||||
curl -sSL "https://go.dev/dl/go${go_version}.linux-${arch_alt}.tar.gz.asc" > "${signature}"
|
||||
gpg --assert-signer="$google_release_key" --verify "${signature}" "${tarball}"
|
||||
}
|
||||
|
||||
function main() {
|
||||
fetch_alpine_minirootfs
|
||||
fetch_golang
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
@ -4,11 +4,11 @@ set -o errexit
|
|||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
FUNC_UTILS_IMG="localhost:50000/knative/func-utils:latest"
|
||||
FUNC_UTILS_IMG="localhost:50000/knative/func-utils:v2"
|
||||
|
||||
"$(dirname "$(realpath "$0")")/fetch-util-img-prerequisites.sh"
|
||||
CGO_ENABLED=0 go build -o "func-util" -trimpath -ldflags '-w -s' ./cmd/func-util
|
||||
|
||||
docker build . -f Dockerfile.utils -t "${FUNC_UTILS_IMG}"
|
||||
docker build . -f Dockerfile.utils -t "${FUNC_UTILS_IMG}" --build-arg FUNC_UTIL_BINARY=func-util
|
||||
docker push "${FUNC_UTILS_IMG}"
|
||||
|
||||
# Build custom buildah image for tests.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import (
|
|||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
||||
var SocatImage = "ghcr.io/knative/func-utils:latest"
|
||||
var SocatImage = "ghcr.io/knative/func-utils:v2"
|
||||
|
||||
// NewInClusterDialer creates context dialer that will dial TCP connections via POD running in k8s cluster.
|
||||
// This is useful when accessing k8s services that are not exposed outside cluster (e.g. openshift image registry).
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func DeletePersistentVolumeClaims(ctx context.Context, namespaceOverride string,
|
|||
return client.CoreV1().PersistentVolumeClaims(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
||||
var TarImage = "ghcr.io/knative/func-utils:latest"
|
||||
var TarImage = "ghcr.io/knative/func-utils:v2"
|
||||
|
||||
// UploadToVolume uploads files (passed in form of tar stream) into volume.
|
||||
func UploadToVolume(ctx context.Context, content io.Reader, claimName, namespace string) error {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var DeployerImage = "ghcr.io/knative/func-utils:latest"
|
||||
var DeployerImage = "ghcr.io/knative/func-utils:v2"
|
||||
|
||||
func getBuildpackTask() string {
|
||||
return `apiVersion: tekton.dev/v1
|
||||
|
|
@ -306,37 +306,21 @@ spec:
|
|||
- name: generate
|
||||
image: %s
|
||||
workingDir: $(workspaces.source.path)
|
||||
args: ["$(params.ENV_VARS[*])"]
|
||||
script: |
|
||||
echo "Processing Build Environment Variables"
|
||||
echo "" > /env-vars/env-file
|
||||
for var in "$@"
|
||||
do
|
||||
if [[ "$var" != "=" ]]; then
|
||||
echo "$var" >> /env-vars/env-file
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Generated Build Env Var file"
|
||||
echo "------------------------------"
|
||||
cat /env-vars/env-file
|
||||
echo "------------------------------"
|
||||
|
||||
/usr/local/bin/s2i --loglevel=$(params.LOGLEVEL) build --keep-symlinks $(params.PATH_CONTEXT) $(params.BUILDER_IMAGE) \
|
||||
--image-scripts-url $(params.S2I_IMAGE_SCRIPTS_URL) \
|
||||
--as-dockerfile /gen-source/Dockerfile.gen --environment-file /env-vars/env-file
|
||||
|
||||
echo "Preparing func.yaml for later deployment"
|
||||
func_file="$(workspaces.source.path)/func.yaml"
|
||||
if [ "$(params.PATH_CONTEXT)" != "" ]; then
|
||||
func_file="$(workspaces.source.path)/$(params.PATH_CONTEXT)/func.yaml"
|
||||
fi
|
||||
sed -i "s|^registry:.*$|registry: $(params.REGISTRY)|" "$func_file"
|
||||
echo "Function image registry: $(params.REGISTRY)"
|
||||
|
||||
s2iignore_file="$(dirname "$func_file")/.s2iignore"
|
||||
[ -f "$s2iignore_file" ] || echo "node_modules" >> "$s2iignore_file"
|
||||
|
||||
command:
|
||||
- s2i-generate
|
||||
- "--target"
|
||||
- /gen-source
|
||||
- "--path-context"
|
||||
- $(params.PATH_CONTEXT)
|
||||
- "--builder-image"
|
||||
- $(params.BUILDER_IMAGE)
|
||||
- "--registry"
|
||||
- $(params.REGISTRY)
|
||||
- "--image-script-url"
|
||||
- $(params.S2I_IMAGE_SCRIPTS_URL)
|
||||
- "--log-level"
|
||||
- $(params.LOGLEVEL)
|
||||
- $(params.ENV_VARS[*])
|
||||
volumeMounts:
|
||||
- mountPath: /gen-source
|
||||
name: gen-source
|
||||
|
|
@ -418,8 +402,7 @@ spec:
|
|||
steps:
|
||||
- name: func-deploy
|
||||
image: "%s"
|
||||
script: |
|
||||
deploy $(params.path) "$(params.image)"
|
||||
command: ["deploy", "$(params.path)", "$(params.image)"]
|
||||
`, DeployerImage)
|
||||
}
|
||||
|
||||
|
|
@ -446,8 +429,7 @@ spec:
|
|||
steps:
|
||||
- name: func-scaffold
|
||||
image: %s
|
||||
script: |
|
||||
scaffold $(params.path)
|
||||
command: ["scaffold", "$(params.path)"]
|
||||
`, DeployerImage)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue