Skip to content

[Refactoring] API should not use its local file system to handle requests #3

@dayeol

Description

@dayeol

Currently, the DCR API is using its own file system to create a build context (a tar file) for a Kaniko job.

func (k *KubernetesBuildService) CreateBuildCtx(ctx context.Context, creator string) (io.ReadCloser, error) {
provider := cloud.GetCloudProvider(k.ctx)
workingDir, err := utils.GetWorkDirectory()
if err != nil {
return nil, err
}
// change working dir to parent
err = os.Chdir(workingDir)
if err != nil {
return nil, errors.Wrap(err, "failed to change work directory")
}
// create directory for the user
directory := filepath.Clean(creator)
// remove old user directory
err = os.RemoveAll(directory)
if err != nil {
if !os.IsNotExist(err) {
return nil, errors.Wrap(err, "failed to remove user directory")
}
}
// create user directory
err = os.MkdirAll(directory, 0700)
if err != nil {
return nil, errors.Wrap(err, "failed to create directory for user")
}
userWorkspaceTar := filepath.Join(directory, config.GetUserWorkspaceFile(creator))
// download user's workspace, it's tar.gz file
if err = provider.DownloadFile(config.GetUserWorkSpacePath(creator), userWorkspaceTar); err != nil {
return nil, err
}
// unzip the user's workspace
if err = utils.UnTarGz(userWorkspaceTar, directory); err != nil {
return nil, err
}
dockerFile := utils.GetDockerFile()
// copy dockerfile to directory
err = utils.CopyFile(dockerFile, fmt.Sprintf("%s/Dockerfile", directory))
if err != nil {
return nil, err
}
configPath := utils.GetConfigFile()
if err != nil {
return nil, err
}
// copy config file to directory
err = utils.CopyFile(configPath, fmt.Sprintf("%s/config.yaml", directory))
if err != nil {
return nil, err
}
buildCtx, err := archive.TarWithOptions(directory, &archive.TarOptions{})
if err != nil {
return nil, err
}
return buildCtx, nil
}

This is not ideal because of a few reasons:
(1) Performance - File I/O is extremely slow, so it will likely increase the overall API latency by an order of magnitude.
(2) Statelessness - API needs to remain stateless, where using file system obviously make it hard
(3) Security - using file system makes requests essentially share the same system resources, leading potential security risks.

Change it not to use the file system. Instead, we can use bytes.Buffer and tar.NewWriter to do everything in memory.

reference: https://go.dev/src/archive/tar/example_test.go

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions