mirror of https://github.com/knative/func.git
191 lines
4.1 KiB
Go
191 lines
4.1 KiB
Go
//go:build exclude_graphdriver_btrfs || !cgo
|
|
// +build exclude_graphdriver_btrfs !cgo
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"slices"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
|
|
"github.com/openshift/source-to-image/pkg/cmd/cli"
|
|
"k8s.io/klog/v2"
|
|
|
|
"knative.dev/func/pkg/builders/s2i"
|
|
fn "knative.dev/func/pkg/functions"
|
|
"knative.dev/func/pkg/k8s"
|
|
"knative.dev/func/pkg/knative"
|
|
"knative.dev/func/pkg/scaffolding"
|
|
"knative.dev/func/pkg/tar"
|
|
)
|
|
|
|
func main() {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
sigs := make(chan os.Signal, 1)
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
|
go func() {
|
|
<-sigs
|
|
cancel()
|
|
<-sigs // second sigint/sigterm is treated as sigkill
|
|
os.Exit(137)
|
|
}()
|
|
|
|
var cmd func(context.Context) error = unknown
|
|
|
|
switch filepath.Base(os.Args[0]) {
|
|
case "deploy":
|
|
cmd = deploy
|
|
case "scaffold":
|
|
cmd = scaffold
|
|
case "s2i":
|
|
cmd = s2iCmd
|
|
case "socat":
|
|
cmd = socat
|
|
case "sh":
|
|
cmd = sh
|
|
}
|
|
|
|
err := cmd(ctx)
|
|
if err != nil {
|
|
_, _ = fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func unknown(_ context.Context) error {
|
|
return fmt.Errorf("unknown command: %q", os.Args[0])
|
|
}
|
|
|
|
func socat(ctx context.Context) error {
|
|
cmd := newSocatCmd()
|
|
cmd.SetContext(ctx)
|
|
return cmd.Execute()
|
|
}
|
|
|
|
func scaffold(ctx context.Context) error {
|
|
|
|
if len(os.Args) != 2 {
|
|
return fmt.Errorf("expected exactly one positional argument (function project path)")
|
|
}
|
|
|
|
path := os.Args[1]
|
|
|
|
f, err := fn.NewFunction(path)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot load func project: %w", err)
|
|
}
|
|
|
|
if f.Runtime != "go" {
|
|
// Scaffolding is for now supported/needed only for Go.
|
|
return nil
|
|
}
|
|
|
|
embeddedRepo, err := fn.NewRepository("", "")
|
|
if err != nil {
|
|
return fmt.Errorf("cannot initialize repository: %w", err)
|
|
}
|
|
|
|
appRoot := filepath.Join(f.Root, ".s2i", "builds", "last")
|
|
_ = os.RemoveAll(appRoot)
|
|
|
|
err = scaffolding.Write(appRoot, f.Root, f.Runtime, f.Invoke, embeddedRepo.FS())
|
|
if err != nil {
|
|
return fmt.Errorf("cannot write the scaffolding: %w", err)
|
|
}
|
|
|
|
if err := os.MkdirAll(filepath.Join(f.Root, ".s2i", "bin"), 0755); err != nil {
|
|
return fmt.Errorf("unable to create .s2i bin dir. %w", err)
|
|
}
|
|
|
|
if err := os.WriteFile(filepath.Join(f.Root, ".s2i", "bin", "assemble"), []byte(s2i.GoAssembler), 0755); err != nil {
|
|
return fmt.Errorf("unable to write go assembler. %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func s2iCmd(ctx context.Context) error {
|
|
klog.InitFlags(flag.CommandLine)
|
|
cmd := cli.CommandFor()
|
|
cmd.SetContext(ctx)
|
|
return cmd.Execute()
|
|
}
|
|
|
|
func deploy(ctx context.Context) error {
|
|
var err error
|
|
deployer := knative.NewDeployer(
|
|
knative.WithDeployerVerbose(true),
|
|
knative.WithDeployerDecorator(deployDecorator{}))
|
|
|
|
var root string
|
|
if len(os.Args) > 1 {
|
|
root = os.Args[1]
|
|
} else {
|
|
root, err = os.Getwd()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot determine working directory: %w", err)
|
|
}
|
|
}
|
|
|
|
f, err := fn.NewFunction(root)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot load function: %w", err)
|
|
}
|
|
if len(os.Args) > 2 {
|
|
f.Deploy.Image = os.Args[2]
|
|
}
|
|
if f.Deploy.Image == "" {
|
|
f.Deploy.Image = f.Image
|
|
}
|
|
|
|
res, err := deployer.Deploy(ctx, f)
|
|
if err != nil {
|
|
return fmt.Errorf("cannont deploy the function: %w", err)
|
|
}
|
|
|
|
fmt.Printf("function has been deployed\n%+v\n", res)
|
|
return nil
|
|
}
|
|
|
|
type deployDecorator struct {
|
|
oshDec k8s.OpenshiftMetadataDecorator
|
|
}
|
|
|
|
func (d deployDecorator) UpdateAnnotations(function fn.Function, annotations map[string]string) map[string]string {
|
|
if k8s.IsOpenShift() {
|
|
return d.oshDec.UpdateAnnotations(function, annotations)
|
|
}
|
|
return annotations
|
|
}
|
|
|
|
func (d deployDecorator) UpdateLabels(function fn.Function, labels map[string]string) map[string]string {
|
|
if k8s.IsOpenShift() {
|
|
return d.oshDec.UpdateLabels(function, labels)
|
|
}
|
|
return labels
|
|
}
|
|
|
|
func sh(ctx context.Context) error {
|
|
if !slices.Equal(os.Args[1:], []string{"-c", "umask 0000 && exec tar -xmf -"}) {
|
|
return fmt.Errorf("this is a fake sh (only for backward compatiblility purposes)")
|
|
}
|
|
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return fmt.Errorf("cannot get working directory: %w", err)
|
|
}
|
|
|
|
unix.Umask(0)
|
|
|
|
return tar.Extract(os.Stdin, wd)
|
|
}
|