blob: 757646d263a7335f49cb105b4e7879db917e4fe4 [file]
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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.
package pack
import (
"bytes"
"context"
"fmt"
"github.com/apache/dubbo-kubernetes/cli/pkg/hub"
"github.com/apache/dubbo-kubernetes/cli/pkg/hub/builder"
"github.com/apache/dubbo-kubernetes/cli/pkg/sdk/dubbo"
pack "github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/logging"
"github.com/buildpacks/pack/pkg/project/types"
"github.com/docker/docker/client"
"github.com/heroku/color"
"io"
"runtime"
"time"
)
const DefaultName = builder.Pack
var (
DefaultGoBuilder = "sca-registry.cn-hangzhou.cr.aliyuncs.com/dubbo/builder:24"
DefaultJavaBuilder = "sca-registry.cn-hangzhou.cr.aliyuncs.com/dubbo/builder:24"
)
var (
DefaultBuilderImages = map[string]string{
"go": DefaultGoBuilder,
"java": DefaultJavaBuilder,
}
defaultBuildpacks = map[string][]string{}
)
type Builder struct {
name string
outBuffer bytes.Buffer
logger logging.Logger
impl Impl
withTimestamp bool
}
type Impl interface {
Build(context.Context, pack.BuildOptions) error
}
type Option func(*Builder)
func NewBuilder(options ...Option) *Builder {
b := &Builder{name: DefaultName}
for _, o := range options {
o(b)
}
b.logger = logging.NewLogWithWriters(color.Stdout(), color.Stderr(), logging.WithVerbose())
return b
}
func BuilderImage(dc *dubbo.DubboConfig, builderName string) (string, error) {
return builder.Image(dc, builderName, DefaultBuilderImages)
}
func (b *Builder) Build(ctx context.Context, dc *dubbo.DubboConfig) (err error) {
image, err := BuilderImage(dc, b.name)
if err != nil {
return
}
buildpacks := dc.Build.Buildpacks
if len(buildpacks) == 0 {
buildpacks = defaultBuildpacks[dc.Runtime]
}
opts := pack.BuildOptions{
AppPath: dc.Root,
Image: dc.Image,
Builder: image,
Buildpacks: buildpacks,
ProjectDescriptor: types.Descriptor{
Build: types.Build{
Exclude: []string{},
},
},
ContainerConfig: struct {
Network string
Volumes []string
}{Network: "", Volumes: nil},
}
if b.withTimestamp {
now := time.Now()
opts.CreationTime = &now
}
if runtime.GOOS == "linux" {
opts.ContainerConfig.Network = "host"
}
impl := b.impl
if impl == nil {
var (
cli client.CommonAPIClient
dockerHost string
)
cli, dockerHost, err = hub.NewClient(client.DefaultDockerHost)
if err != nil {
return fmt.Errorf("cannot create docker client: %w", err)
}
defer cli.Close()
opts.DockerHost = dockerHost
if impl, err = pack.NewClient(pack.WithLogger(b.logger), pack.WithDockerClient(cli)); err != nil {
return fmt.Errorf("cannot create pack client: %w", err)
}
}
if err = impl.Build(ctx, opts); err != nil {
if ctx.Err() != nil {
return
} else {
err = fmt.Errorf("failed to build the application: %w", err)
fmt.Fprintln(color.Stderr(), "")
_, _ = io.Copy(color.Stderr(), &b.outBuffer)
fmt.Fprintln(color.Stderr(), "")
}
}
return
}