Skip to content

Commit

Permalink
Run func without HOME defined/ unaccessible .config dir (#2236)
Browse files Browse the repository at this point in the history
* fixed integration tests

Signed-off-by: gauron99 <[email protected]>

* def creds back

Signed-off-by: gauron99 <[email protected]>

* docker config.json credentials test when HOME not defined

Signed-off-by: gauron99 <[email protected]>

* pack test

Signed-off-by: gauron99 <[email protected]>

* simplify

Signed-off-by: gauron99 <[email protected]>

* og creds, small fixes

Signed-off-by: gauron99 <[email protected]>

* s2i test no home

Signed-off-by: gauron99 <[email protected]>

* remove unnecessary stuff

Signed-off-by: gauron99 <[email protected]>

* deploy test without home

Signed-off-by: gauron99 <[email protected]>

* confict fix after rebase

Signed-off-by: gauron99 <[email protected]>

* move test, dont delete

Signed-off-by: gauron99 <[email protected]>

* runtime change

Signed-off-by: gauron99 <[email protected]>

* node image signals fixed and smaller size for GH actions

Signed-off-by: gauron99 <[email protected]>

* return err

Signed-off-by: gauron99 <[email protected]>

* cred test

Signed-off-by: gauron99 <[email protected]>

* clean up comments

Signed-off-by: gauron99 <[email protected]>

---------

Signed-off-by: gauron99 <[email protected]>
  • Loading branch information
gauron99 authored Jun 4, 2024
1 parent a2bc6f6 commit aa909bd
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 23 deletions.
3 changes: 0 additions & 3 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,6 @@ func runBuild(cmd *cobra.Command, _ []string, newClient ClientFactory) (err erro
cfg buildConfig
f fn.Function
)
if err = config.CreatePaths(); err != nil { // for possible auth.json usage
return
}
if cfg, err = newBuildConfig().Prompt(); err != nil { // gather values into a single instruction set
return
}
Expand Down
3 changes: 0 additions & 3 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,6 @@ func runDeploy(cmd *cobra.Command, newClient ClientFactory) (err error) {
cfg deployConfig
f fn.Function
)
if err = config.CreatePaths(); err != nil { // for possible auth.json usage
return
}
if cfg, err = newDeployConfig(cmd).Prompt(); err != nil {
return
}
Expand Down
33 changes: 33 additions & 0 deletions cmd/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1894,3 +1894,36 @@ func TestDeploy_NoErrorOnOldFunctionNotFound(t *testing.T) {
t.Fatal(err)
}
}

// TestDeploy_WithoutHome ensures that deploying a function without HOME &
// XDG_CONFIG_HOME defined succeeds
func TestDeploy_WithoutHome(t *testing.T) {
var (
root = FromTempDirectory(t)
ns = "myns"
)

t.Setenv("HOME", "")
t.Setenv("XDG_CONFIG_HOME", "")

// Create a basic go Function
f := fn.Function{
Runtime: "go",
Root: root,
}
_, err := fn.New().Init(f)
if err != nil {
t.Fatal(err)
}

// Deploy the function
cmd := NewDeployCmd(NewTestClient(
fn.WithDeployer(mock.NewDeployer()),
fn.WithRegistry(TestRegistry)))

cmd.SetArgs([]string{fmt.Sprintf("--namespace=%s", ns)})
err = cmd.Execute()
if err != nil {
t.Fatal(err)
}
}
2 changes: 1 addition & 1 deletion pkg/builders/buildpacks/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (b *Builder) Build(ctx context.Context, f fn.Function, platforms []fn.Platf
if err = impl.Build(ctx, opts); err != nil {
if ctx.Err() != nil {
return // SIGINT
} else if !b.verbose {
} else if b.verbose {
err = fmt.Errorf("failed to build the function: %w", err)
fmt.Fprintln(color.Stderr(), "")
_, _ = io.Copy(color.Stderr(), &b.outBuff)
Expand Down
38 changes: 23 additions & 15 deletions pkg/docker/creds/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,24 +165,31 @@ func NewCredentialsProvider(configPath string, opts ...Opt) docker.CredentialsPr
}
}

// default credential loaders map -- load only those that should be there.
var defaultCredentialLoaders = []CredentialsCallback{}

c.authFilePath = filepath.Join(configPath, "auth.json")
sys := &containersTypes.SystemContext{
AuthFilePath: c.authFilePath,
}

home, err := os.UserHomeDir()
if err != nil {
panic(err)
if _, err := os.Stat(c.authFilePath); err == nil {
defaultCredentialLoaders = append(defaultCredentialLoaders,
func(registry string) (docker.Credentials, error) {
return getCredentialsByCredentialHelper(c.authFilePath, registry)
})
}
dockerConfigPath := filepath.Join(home, ".docker", "config.json")

var defaultCredentialLoaders = []CredentialsCallback{
func(registry string) (docker.Credentials, error) {
return getCredentialsByCredentialHelper(c.authFilePath, registry)
},
func(registry string) (docker.Credentials, error) {
return getCredentialsByCredentialHelper(dockerConfigPath, registry)
},
// add only if home dir is defined -- for .docker/config.json creds
home, err := os.UserHomeDir()
if err == nil {
dockerConfigPath := filepath.Join(home, ".docker", "config.json")
defaultCredentialLoaders = append(defaultCredentialLoaders,
func(registry string) (docker.Credentials, error) {
return getCredentialsByCredentialHelper(dockerConfigPath, registry)
})
}
defaultCredentialLoaders = append(defaultCredentialLoaders,
func(registry string) (docker.Credentials, error) {
creds, err := dockerConfig.GetCredentials(sys, registry)
if err != nil {
Expand All @@ -195,7 +202,8 @@ func NewCredentialsProvider(configPath string, opts ...Opt) docker.CredentialsPr
Username: creds.Username,
Password: creds.Password,
}, nil
},
})
defaultCredentialLoaders = append(defaultCredentialLoaders,
func(registry string) (docker.Credentials, error) {
// Fallback onto default docker config locations
emptySys := &containersTypes.SystemContext{}
Expand All @@ -207,11 +215,11 @@ func NewCredentialsProvider(configPath string, opts ...Opt) docker.CredentialsPr
Username: creds.Username,
Password: creds.Password,
}, nil
},
})
defaultCredentialLoaders = append(defaultCredentialLoaders,
func(registry string) (docker.Credentials, error) { // empty credentials provider for unsecured registries
return docker.Credentials{}, nil
},
}
})

c.credentialLoaders = append(c.credentialLoaders, defaultCredentialLoaders...)

Expand Down
80 changes: 79 additions & 1 deletion pkg/docker/creds/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"net/http"
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"sync"
Expand Down Expand Up @@ -284,7 +285,6 @@ func startServer(t *testing.T, uname, pwd string) (addr, addrTLS string) {
panic(err)
}
}()

// make the testing CA trusted by default HTTP transport/client
oldDefaultTransport := http.DefaultTransport
newDefaultTransport := http.DefaultTransport.(*http.Transport).Clone()
Expand Down Expand Up @@ -549,6 +549,77 @@ func TestCredentialsProviderSavingFromUserInput(t *testing.T) {
}
}

// TestCredentialsWithoutHome tests different scenarios when HOME is not set
func TestCredentialsWithoutHome(t *testing.T) {
type args struct {
promptUser creds.CredentialsCallback
verifyCredentials creds.VerifyCredentialsCallback
registry string
setUpEnv setUpEnv
}
tests := []struct {
name string
testHomePathEmpty bool
args args
want Credentials
}{
{
name: "empty home with correct user prompt",
testHomePathEmpty: true,
args: args{
promptUser: correctPwdCallback, // user inputs correct credentials
verifyCredentials: correctVerifyCbk,
registry: "docker.io",
setUpEnv: setEmptyHome,
},
want: Credentials{Username: dockerIoUser, Password: dockerIoUserPwd},
},
{
name: "empty config with user prompt",
args: args{
promptUser: correctPwdCallback,
verifyCredentials: correctVerifyCbk,
registry: "docker.io",
},
want: Credentials{Username: dockerIoUser, Password: dockerIoUserPwd},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resetHomeDir(t)
if tt.args.setUpEnv != nil {
tt.args.setUpEnv(t)
}

// prepare config path for credentials provider
var configPath string
if tt.testHomePathEmpty {
configPath = ""
} else {
configPath = testConfigPath(t)
}

credentialsProvider := creds.NewCredentialsProvider(
configPath,
creds.WithPromptForCredentials(tt.args.promptUser),
creds.WithVerifyCredentials(tt.args.verifyCredentials),
)

got, err := credentialsProvider(context.Background(), tt.args.registry+"/someorg/someimage:sometag")
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("got: %v, want: %v", got, tt.want)
}
})
}
}

// ********************** helper functions below **************************** \\

func resetHomeDir(t *testing.T) {
t.TempDir()
if err := os.RemoveAll(homeTempDir); err != nil {
Expand Down Expand Up @@ -903,3 +974,10 @@ func (i *inMemoryHelper) Delete(serverURL string) error {

return credentials.NewErrCredentialsNotFound()
}

// set home variables to empty values
func setEmptyHome(t *testing.T) {
t.Helper()
t.Setenv("HOME", "")
t.Setenv("XDG_CONFIG_HOME", "")
}
47 changes: 47 additions & 0 deletions pkg/functions/client_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/docker/docker/client"

"knative.dev/func/pkg/builders/buildpacks"
"knative.dev/func/pkg/builders/s2i"
"knative.dev/func/pkg/docker"
fn "knative.dev/func/pkg/functions"
"knative.dev/func/pkg/knative"
Expand Down Expand Up @@ -545,6 +546,31 @@ func Handle(ctx context.Context, w http.ResponseWriter, req *http.Request) {
}
}

// TestDeployWithoutHome ensures that running client.New works without
// home
func TestDeployWithoutHome(t *testing.T) {
root, cleanup := Mktemp(t)
defer cleanup()

t.Setenv("HOME", "")
t.Setenv("XDG_CONFIG_HOME", "")
verbose := false
name := "test-deploy-no-home"

f := fn.Function{Runtime: "node", Name: name, Root: root, Namespace: DefaultNamespace}

// client with s2i builder because pack needs HOME
client := newClientWithS2i(verbose)

// expect to succeed
_, _, err := client.New(context.Background(), f)
if err != nil {
t.Fatalf("expected no errors but got %v", err)
}

defer del(t, client, name, DefaultNamespace)
}

// ***********
// Helpers
// ***********
Expand All @@ -571,6 +597,27 @@ func newClient(verbose bool) *fn.Client {
)
}

// copy of newClient just builder is s2i instead of buildpacks
func newClientWithS2i(verbose bool) *fn.Client {
builder := s2i.NewBuilder(s2i.WithVerbose(verbose))
pusher := docker.NewPusher(docker.WithVerbose(verbose))
deployer := knative.NewDeployer(knative.WithDeployerVerbose(verbose))
describer := knative.NewDescriber(verbose)
remover := knative.NewRemover(verbose)
lister := knative.NewLister(verbose)

return fn.New(
fn.WithRegistry(DefaultRegistry),
fn.WithVerbose(verbose),
fn.WithBuilder(builder),
fn.WithPusher(pusher),
fn.WithDeployer(deployer),
fn.WithDescriber(describer),
fn.WithRemover(remover),
fn.WithLister(lister),
)
}

// Del cleans up after a test by removing a function by name.
// (test fails if the named function does not exist)
//
Expand Down

0 comments on commit aa909bd

Please sign in to comment.