Skip to content

Commit

Permalink
Merge pull request #317 from yin1999/buildpack-cn
Browse files Browse the repository at this point in the history
feat(dubboctl): add support for using CN mirror of buildpacks toolchain
  • Loading branch information
chickenlj authored Oct 25, 2024
2 parents 479e408 + 8b102b1 commit 08ef0df
Show file tree
Hide file tree
Showing 25 changed files with 682 additions and 538 deletions.
28 changes: 16 additions & 12 deletions dubboctl/cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,23 @@ func (c *buildConfig) Configure(f *dubbo.Dubbo) {
f.Image = c.Image
}

var envs []dubbo.Env
for _, pair := range c.Envs {
parts := strings.Split(pair, "=")

if len(parts) == 2 {
key := &parts[0]
value := &parts[1]
env := dubbo.Env{
Name: key,
Value: value,
if len(c.Envs) > 0 {
envs := map[string]string{}
for _, env := range f.Build.BuildEnvs {
envs[*env.Name] = *env.Value
}
for _, pair := range c.Envs {
parts := strings.Split(pair, "=")
if len(parts) == 2 {
envs[parts[0]] = parts[1]
}
envs = append(envs, env)
}
f.Build.BuildEnvs = make([]dubbo.Env, 0, len(envs))
for k, v := range envs {
f.Build.BuildEnvs = append(f.Build.BuildEnvs, dubbo.Env{
Name: &k,
Value: &v,
})
}
}
f.Build.BuildEnvs = envs
}
5 changes: 5 additions & 0 deletions dubboctl/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ func runCreate(cmd *cobra.Command, args []string, newClient ClientFactory) (err
Root: cfg.Path,
Runtime: cfg.Runtime,
Template: cfg.Template,
Build: dubbo.BuildSpec{
CnMirror: dubbo.BooleanWithComment{
Comment: "Specify `cnMirror: true` to use the mirror in mainland China",
},
},
}, cfg.Init, cmd)
if err != nil {
return err
Expand Down
3 changes: 0 additions & 3 deletions dubboctl/cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,6 @@ func runDeploy(cmd *cobra.Command, newClient ClientFactory) error {
if err := cfg.Validate(cmd); err != nil {
return err
}
if err != nil {
return err
}

if !f.Initialized() {
return dubbo.NewErrNotInitialized(f.Root)
Expand Down
76 changes: 58 additions & 18 deletions dubboctl/internal/builders/pack/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,21 @@ import (
)

import (
pack "github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/buildpack"
packClient "github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/logging"
"github.com/buildpacks/pack/pkg/project/types"

"github.com/distribution/reference"

"github.com/docker/docker/client"

"github.com/heroku/color"
)

import (
"github.com/apache/dubbo-kubernetes/dubboctl/internal/builders"
"github.com/apache/dubbo-kubernetes/dubboctl/internal/builders/pack/mirror"
"github.com/apache/dubbo-kubernetes/dubboctl/internal/docker"
"github.com/apache/dubbo-kubernetes/dubboctl/internal/dubbo"
)
Expand All @@ -46,8 +50,8 @@ import (
const DefaultName = builders.Pack

var (
DefaultBaseBuilder = "ghcr.io/knative/builder-jammy-base:latest"
DefaultTinyBuilder = "ghcr.io/knative/builder-jammy-tiny:latest"
DefaultBaseBuilder = "docker.io/paketobuildpacks/builder-jammy-tiny:latest"
DefaultTinyBuilder = "docker.io/paketobuildpacks/builder-jammy-tiny:latest"
)

var (
Expand All @@ -67,7 +71,17 @@ var (
"ghcr.io/knative/",
}

defaultBuildpacks = map[string][]string{}
defaultBuildpacks = map[string][]string{
"go": {"paketo-buildpacks/go"},
"java": {"paketo-buildpacks/java"},
}

// work around for resolving the images with latest tag could not be mirrored
latestImageTagMapping = map[string]string{
"paketobuildpacks/builder-jammy-tiny": "0.0.271",
"paketobuildpacks/run-jammy-tiny": "0.2.46",
"buildpacksio/lifecycle": "0.17.7",
}
)

// Builder will build Function using Pack.
Expand All @@ -82,7 +96,7 @@ type Builder struct {

// Impl allows for the underlying implementation to be mocked for tests.
type Impl interface {
Build(context.Context, pack.BuildOptions) error
Build(context.Context, packClient.BuildOptions) error
}

// NewBuilder instantiates a Buildpack-based Builder
Expand Down Expand Up @@ -111,8 +125,6 @@ func WithImpl(i Impl) Option {
}
}

var DefaultLifecycleImage = "quay.io/boson/lifecycle@sha256:f53fea9ec9188b92cab0b8a298ff852d76a6c2aaf56f968a08637e13de0e0c59"

func transportEnv(ee []dubbo.Env) (map[string]string, error) {
envs := make(map[string]string, len(ee))
for _, e := range ee {
Expand All @@ -130,6 +142,22 @@ func transportEnv(ee []dubbo.Env) (map[string]string, error) {
return envs, nil
}

// work around for resolving the images with latest tag could not be mirrored
func defaultBuildPackImageReplace(image string) string {
ref, err := reference.ParseDockerRef(image)
if err != nil {
return image
}
if reference.Domain(ref) != "docker.io" {
return image
}
if tag, ok := ref.(reference.Tagged); ok && tag.Tag() == "latest" {
image = fmt.Sprintf("%s/%s:%s", reference.Domain(ref), reference.Path(ref), latestImageTagMapping[reference.Path(ref)])
return image
}
return image
}

// Build the Function at path.
func (b *Builder) Build(ctx context.Context, f *dubbo.Dubbo) (err error) {
// Builder image from the function if defined, default otherwise.
Expand All @@ -140,25 +168,32 @@ func (b *Builder) Build(ctx context.Context, f *dubbo.Dubbo) (err error) {

buildpacks := f.Build.Buildpacks
if len(buildpacks) == 0 {
buildpacks = defaultBuildpacks[f.Runtime]
// check if the default builder image is used
ref, err := reference.ParseDockerRef(image)
if err == nil &&
reference.Domain(ref) == "docker.io" &&
reference.Path(ref) == "paketobuildpacks/builder-jammy-tiny" {
// use the default buildpacks for the runtime
buildpacks = defaultBuildpacks[f.Runtime]
}
}

// Pack build options
opts := pack.BuildOptions{
AppPath: f.Root,
Image: f.Image,
Builder: image,
// LifecycleImage: DefaultLifecycleImage, // TODO add it or not?
opts := packClient.BuildOptions{
AppPath: f.Root,
Image: f.Image,
Builder: image,
Buildpacks: buildpacks,
ProjectDescriptor: types.Descriptor{
Build: types.Build{
Exclude: []string{},
},
},
ContainerConfig: struct {
Network string
Volumes []string
}{Network: "", Volumes: nil},
ContainerConfig: packClient.ContainerConfig{Network: "", Volumes: nil},
// use the default user/group
// 0 means root (which may cause permission issues when running the builder with non-root user)
GroupID: -1,
UserID: -1,
}
if b.withTimestamp {
now := time.Now()
Expand Down Expand Up @@ -192,8 +227,13 @@ func (b *Builder) Build(ctx context.Context, f *dubbo.Dubbo) (err error) {
defer cli.Close()
opts.DockerHost = dockerHost

var fetcher buildpack.ImageFetcher = nil
if f.Build.CnMirror.Value {
fetcher = mirror.NewMirrorFetcher(b.logger, cli, defaultBuildPackImageReplace)
}

// Client with a logger which is enabled if in Verbose mode and a dockerClient that supports SSH docker daemon connection.
if impl, err = pack.NewClient(pack.WithLogger(b.logger), pack.WithDockerClient(cli)); err != nil {
if impl, err = packClient.NewClient(packClient.WithLogger(b.logger), packClient.WithDockerClient(cli), packClient.WithFetcher(fetcher)); err != nil {
return fmt.Errorf("cannot create pack client: %w", err)
}
}
Expand Down
40 changes: 40 additions & 0 deletions dubboctl/internal/builders/pack/mirror/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 mirror

import (
"fmt"
)

type ImageNotFoundError string

func (e ImageNotFoundError) Error() string {
return fmt.Sprintf("pack mirror: image %q not found, please visit https://docker.aityp.com/manage/add to add it", string(e))
}

type ErrLatestTagNotSupported string

func (e ErrLatestTagNotSupported) Error() string {
return fmt.Sprintf("pack mirror: image %q with latest tag is not supported, please specify a specific tag", string(e))
}

type ErrDigestNotSupported string

func (e ErrDigestNotSupported) Error() string {
return fmt.Sprintf("pack mirror: image %q with digest is not supported, please specify a specific tag", string(e))
}
Loading

0 comments on commit 08ef0df

Please sign in to comment.