Pack代码仓地址:https://github.com/buildpacks/pack
过程性内容走读流水账记录,慢慢看,慢慢学,慢慢进步
一、整体逻辑
TODO
1.1 client初始化
Client
是Pack项目中所有构建任务的集成对象,相关命令行的触发最后均有Client
实例进行,而传递的行为则由PackClient
接口进行设计和约束,代码实现目录在pkg/client
。
设计比较好的若干点:
- 参数控制:cfg内容是来源pack输入的toml文件,比如:RunImages、PullPolicy等内容,这个文件内容实际会根据业务配置演进会逐步调整扩展,把内容封装到
config.Config
中保证了参数传递的完整性; - 参数器扩展:
NewClient()
过程中client的属性注入用各类装饰器函数(client.WithXXX()
)进行封装,而且NewClient()
接收的是可变参数确保其可扩展性。当然如果不这样去实现,直接用if ...
去配置client属性对象也行,但需要加一个属性就要多写至少两行,代码会持续冗余化。GO编程模式:修饰器
// Client is an orchestration object, it contains all parameters needed to
// build an app image using Cloud Native Buildpacks.
// All settings on this object should be changed through ClientOption functions.
type Client struct {
logger logging.Logger
docker dockerClient.CommonAPIClient
keychain authn.Keychain
imageFactory ImageFactory
imageFetcher ImageFetcher
downloader BlobDownloader
lifecycleExecutor LifecycleExecutor
buildpackDownloader BuildpackDownloader
experimental bool
registryMirrors map[string]string
version string
}
func initClient(logger logging.Logger, cfg config.Config) (*client.Client, error) {
dc, err := tryInitSSHDockerClient()
if err != nil {
return nil, err
}
return client.NewClient(client.WithLogger(logger), client.WithExperimental(cfg.Experimental), client.WithRegistryMirrors(cfg.RegistryMirrors), client.WithDockerClient(dc))
}
// internal/commands/commands.go
type PackClient interface {
InspectBuilder(string, bool, ...client.BuilderInspectionModifier) (*client.BuilderInfo, error)
InspectImage(string, bool) (*client.ImageInfo, error)
Rebase(context.Context, client.RebaseOptions) error
CreateBuilder(context.Context, client.CreateBuilderOptions) error
NewBuildpack(context.Context, client.NewBuildpackOptions) error
PackageBuildpack(ctx context.Context, opts client.PackageBuildpackOptions) error
Build(context.Context, client.BuildOptions) error
RegisterBuildpack(context.Context, client.RegisterBuildpackOptions) error
YankBuildpack(client.YankBuildpackOptions) error
InspectBuildpack(client.InspectBuildpackOptions) (*client.BuildpackInfo, error)
PullBuildpack(context.Context, client.PullBuildpackOptions) error
DownloadSBOM(name string, options client.DownloadSBOMOptions) error
}
1.2 imageFactory
用于构建镜像的工厂方法,是Client
的属性之一。ImageFactory
用于设计并约束Client.imageFactory
的行为动作,而imageFactory
对象则是对接口函数的实现。如果不用ImageFactory
接口及imageFactory
结构体对具体动作进行封装则也能通过对client.Client
增加docketClient
以及添加NewImage()
函数实现相关功能,但此类实现方式和原先方式相比有两个弱点:
- 没有对
Client
中的属性动作进行定义约束,即只有实现,没有抽象,并导致类似NewImage()
等功能函数都在Client
中实现; Client
的扩展性会变弱,对于NewImage()
而言,如果要构建有特殊属性的镜像,则需要硬改原有代码,用了imageFactory
则仅需在创建一个xxImageFactory
即可达到目标。 在NewImage()
函数中,还有一个优点是imageutil
等通用工具类都进行了提取封装。
// pkg/client/client.go
// ImageFactory is an interface representing the ability to create a new OCI image.
type ImageFactory interface {
// NewImage initializes an image object with required settings so that it
// can be written either locally or to a registry.
NewImage(repoName string, local bool, imageOS string) (imgutil.Image, error)
}
// pkg/client/client.go
type imageFactory struct {
dockerClient dockerClient.CommonAPIClient
keychain authn.Keychain
}
func (f *imageFactory) NewImage(repoName string, daemon bool, imageOS string) (imgutil.Image, error) {
platform := imgutil.Platform{OS: imageOS}
if daemon {
return local.NewImage(repoName, f.dockerClient, local.WithDefaultPlatform(platform))
}
return remote.NewImage(repoName, f.keychain, remote.WithDefaultPlatform(platform))
}
二、单元测试
2.1 测试目录结构
go语言项目目录设计可以参见project-layout。
- testdata: 用于存放测试执行数据;
- testhelpers: 用于管理测试过程中用到一些工具类,而comparehelpers则是管理比对工具类;
- internal/commands/testmocks: 用mockgen对
PackClient
结构体的测试打桩 Go Mock (gomock)简明教程;
├── 业务其他模块
├── internal
│ ├── 业务其他模块
│ ├── commands
│ │ ├── 业务其他模块
│ │ ├── fakes
│ │ ├── testdata
│ │ ├── testmocks
├── testdata
│ ├── builder.toml
│ ├── buildpack
│ ├── buildpack2
│ ├── buildpack-api-0.4
│ ├── downloader
│ ├── empty-file
│ ├── jar-file.jar
│ ├── just-a-file.txt
│ ├── lifecycle
│ ├── non-zip-file
│ ├── registry
│ ├── some-app
│ └── zip-file.zip
├── testhelpers
├── arg_patterns.go
├── assert_file.go
├── assertions.go
├── comparehelpers
├── registry.go
├── tar_assertions.go
├── tar_verifier.go
└── testhelpers.go