Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"knative.dev/func/pkg/config"
"knative.dev/func/pkg/docker"
fn "knative.dev/func/pkg/functions"
"knative.dev/func/pkg/k8s"
"knative.dev/func/pkg/oci"
"knative.dev/func/pkg/s2i"
)
Expand Down Expand Up @@ -171,8 +172,12 @@ func runBuild(cmd *cobra.Command, _ []string, newClient ClientFactory) (err erro

f = cfg.Configure(f) // Returns an f updated with values from the config (flags, envs, etc)

kc := k8s.NewClient(k8s.BuildClientConfig("", "", fn.Local{}))

f.Registry = resolveRegistry(f.Registry, "", kc)

// Client
clientOptions, err := cfg.clientOptions()
clientOptions, err := cfg.clientOptions(kc)
if err != nil {
return
}
Expand Down Expand Up @@ -214,6 +219,14 @@ func warnRegistryInsecureChange(w io.Writer, newRegistry string, f fn.Function)
}
}

// warnClusterChange determines if the cluster is being changed deliberately and
// if so, warn the user that creds might need to be added
func warnClusterChange(w io.Writer, newCluster string, oldCluster string) {
if newCluster != "" && oldCluster != "" && newCluster != oldCluster {
fmt.Fprintf(w, "Warning: changing cluster from '%s' to '%s'. Ensure your credentials are valid for the new cluster.\n", oldCluster, newCluster)
}
}

type buildConfig struct {
// Globals (builder, confirm, registry, verbose)
config.Global
Expand Down Expand Up @@ -264,8 +277,9 @@ func newBuildConfig() buildConfig {
return buildConfig{
Global: config.Global{
Builder: viper.GetString("builder"),
Cluster: viper.GetString("cluster"),
Confirm: viper.GetBool("confirm"),
Registry: registry(), // deferred defaulting
Registry: viper.GetString("registry"),
Verbose: viper.GetBool("verbose"),
RegistryInsecure: viper.GetBool("registry-insecure"),
},
Expand Down Expand Up @@ -441,22 +455,22 @@ func (c buildConfig) Validate(cmd *cobra.Command) (err error) {
// TODO: As a further optimization, it might be ideal to only build the
// image necessary for the target cluster, since the end product of a function
// deployment is not the container, but rather the running service.
func (c buildConfig) clientOptions() ([]fn.Option, error) {
func (c buildConfig) clientOptions(kc *k8s.Client) ([]fn.Option, error) {
o := []fn.Option{
fn.WithRegistry(c.Registry),
fn.WithRegistryInsecure(c.RegistryInsecure),
}

t := newTransport(c.RegistryInsecure)
creds := newCredentialsProvider(config.Dir(), t, c.RegistryAuthfile, c.RegistryInsecure)
t := newTransport(c.RegistryInsecure, kc)
creds := newCredentialsProvider(config.Dir(), t, c.RegistryAuthfile, c.RegistryInsecure, kc)

switch c.Builder {
case builders.Host:
o = append(o,
fn.WithScaffolder(oci.NewScaffolder(c.Verbose)),
fn.WithBuilder(oci.NewBuilder(builders.Host, c.Verbose)),
fn.WithPusher(oci.NewPusher(c.RegistryInsecure, false, c.Verbose,
oci.WithTransport(newTransport(c.RegistryInsecure)),
oci.WithTransport(newTransport(c.RegistryInsecure, kc)),
oci.WithCredentialsProvider(creds),
oci.WithVerbose(c.Verbose))),
)
Expand Down
66 changes: 37 additions & 29 deletions cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type ClientConfig struct {

// Allow insecure server connections when using SSL
InsecureSkipVerify bool

// Constructed k8s client config to be used with optional overrides
K8sClient *k8s.Client
}

// ClientFactory defines a constructor which assists in the creation of a Client
Expand Down Expand Up @@ -59,32 +62,36 @@ func NewTestClient(options ...fn.Option) ClientFactory {
// the currently configured is used.
// 'Verbose' indicates the system should write out a higher amount of logging.
func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {
kc := cfg.K8sClient
if kc == nil {
kc = k8s.NewClient(k8s.BuildClientConfig("", "", fn.Local{}))
}
var (
t = newTransport(cfg.InsecureSkipVerify) // may provide a custom impl which proxies
c = newCredentialsProvider(config.Dir(), t, "", cfg.InsecureSkipVerify) // for accessing registries
d = newKnativeDeployer(cfg.Verbose) // default deployer (can be overridden via options)
pp = newTektonPipelinesProvider(c, cfg.Verbose, t)
t = newTransport(cfg.InsecureSkipVerify, kc) // may provide a custom impl which proxies
c = newCredentialsProvider(config.Dir(), t, "", cfg.InsecureSkipVerify, kc) // for accessing registries
d = newKnativeDeployer(cfg.Verbose, kc) // default deployer (can be overridden via options)
pp = newTektonPipelinesProvider(c, cfg.Verbose, t, kc)
o = []fn.Option{ // standard (shared) options for all commands
fn.WithVerbose(cfg.Verbose),
fn.WithTransport(t),
fn.WithRepositoriesPath(config.RepositoriesPath()),
fn.WithScaffolder(buildpacks.NewScaffolder(cfg.Verbose)),
fn.WithBuilder(buildpacks.NewBuilder(buildpacks.WithVerbose(cfg.Verbose))),
fn.WithRemovers(knative.NewRemover(cfg.Verbose), k8s.NewRemover(cfg.Verbose), keda.NewRemover(cfg.Verbose)),
fn.WithRemovers(knative.NewRemover(kc, cfg.Verbose), k8s.NewRemover(kc, cfg.Verbose), keda.NewRemover(kc, cfg.Verbose)),
fn.WithDescribers(
knative.NewDescriber(cfg.Verbose, knative.WithDescriberTransport(t)),
k8s.NewDescriber(cfg.Verbose, k8s.WithDescriberTransport(t)),
keda.NewDescriber(cfg.Verbose, keda.WithDescriberTransport(t)),
knative.NewDescriber(kc, cfg.Verbose, knative.WithDescriberTransport(t)),
k8s.NewDescriber(kc, cfg.Verbose, k8s.WithDescriberTransport(t)),
keda.NewDescriber(kc, cfg.Verbose, keda.WithDescriberTransport(t)),
),
fn.WithListers(knative.NewLister(cfg.Verbose), k8s.NewLister(cfg.Verbose), keda.NewLister(cfg.Verbose)),
fn.WithListers(knative.NewLister(kc, cfg.Verbose), k8s.NewLister(kc, cfg.Verbose), keda.NewLister(kc, cfg.Verbose)),
fn.WithDeployer(d),
fn.WithPipelinesProvider(pp),
fn.WithPusher(docker.NewPusher(
docker.WithCredentialsProvider(c),
docker.WithTransport(t),
docker.WithVerbose(cfg.Verbose),
docker.WithInsecure(cfg.InsecureSkipVerify))),
fn.WithSyncer(operator.NewSyncer(operator.WithCredentialsProvider(c))),
fn.WithSyncer(operator.NewSyncer(kc, operator.WithCredentialsProvider(c))),
}
)

Expand All @@ -105,17 +112,17 @@ func NewClient(cfg ClientConfig, options ...fn.Option) (*fn.Client, func()) {

// newTransport returns a transport with cluster-flavor-specific variations
// which take advantage of additional features offered by cluster variants.
func newTransport(insecureSkipVerify bool) fnhttp.RoundTripCloser {
return fnhttp.NewRoundTripper(fnhttp.WithInsecureSkipVerify(insecureSkipVerify), fnhttp.WithOpenShiftServiceCA())
func newTransport(insecureSkipVerify bool, c *k8s.Client) fnhttp.RoundTripCloser {
return fnhttp.NewRoundTripper(c, fnhttp.WithInsecureSkipVerify(insecureSkipVerify), fnhttp.WithOpenShiftServiceCA(c))
}

// newCredentialsProvider returns a credentials provider which possibly
// has cluster-flavor specific additional credential loaders to take advantage
// of features or configuration nuances of cluster variants.
// If authFilePath is provided (non-empty), it will be used as the primary auth file.
// When insecure is true, credential verification uses plain HTTP instead of HTTPS.
func newCredentialsProvider(configPath string, t http.RoundTripper, authFilePath string, insecure bool) oci.CredentialsProvider {
additionalLoaders := append(k8s.GetOpenShiftDockerCredentialLoaders(), k8s.GetGoogleCredentialLoader()...)
func newCredentialsProvider(configPath string, t http.RoundTripper, authFilePath string, insecure bool, k8sClient *k8s.Client) oci.CredentialsProvider {
additionalLoaders := append(k8s.GetOpenShiftDockerCredentialLoaders(k8sClient), k8s.GetGoogleCredentialLoader()...)
additionalLoaders = append(additionalLoaders, k8s.GetECRCredentialLoader()...)
additionalLoaders = append(additionalLoaders, k8s.GetACRCredentialLoader()...)

Expand Down Expand Up @@ -152,57 +159,58 @@ func newCredentialsProvider(configPath string, t http.RoundTripper, authFilePath
return creds.NewCredentialsProvider(configPath, options...)
}

func newTektonPipelinesProvider(creds oci.CredentialsProvider, verbose bool, transport http.RoundTripper) *tekton.PipelinesProvider {
func newTektonPipelinesProvider(creds oci.CredentialsProvider, verbose bool, transport http.RoundTripper, kc *k8s.Client) *tekton.PipelinesProvider {
options := []tekton.Opt{
tekton.WithCredentialsProvider(creds),
tekton.WithVerbose(verbose),
tekton.WithPipelineDecorator(deployDecorator{}),
tekton.WithPipelineDecorator(deployDecorator{k8sClient: kc}),
tekton.WithTransport(transport),
}

return tekton.NewPipelinesProvider(options...)
return tekton.NewPipelinesProvider(kc, options...)
}

func newKnativeDeployer(verbose bool) fn.Deployer {
func newKnativeDeployer(verbose bool, kc *k8s.Client) fn.Deployer {
options := []knative.DeployerOpt{
knative.WithDeployerVerbose(verbose),
knative.WithDeployerDecorator(deployDecorator{}),
knative.WithDeployerDecorator(deployDecorator{k8sClient: kc}),
}

return knative.NewDeployer(options...)
return knative.NewDeployer(kc, options...)
}

func newK8sDeployer(verbose bool) fn.Deployer {
func newK8sDeployer(verbose bool, kc *k8s.Client) fn.Deployer {
options := []k8s.DeployerOpt{
k8s.WithDeployerVerbose(verbose),
k8s.WithDeployerDecorator(deployDecorator{}),
k8s.WithDeployerDecorator(deployDecorator{k8sClient: kc}),
}

return k8s.NewDeployer(options...)
return k8s.NewDeployer(kc, options...)
}

func newKedaDeployer(verbose bool) fn.Deployer {
func newKedaDeployer(verbose bool, kc *k8s.Client) fn.Deployer {
options := []keda.DeployerOpt{
keda.WithDeployerVerbose(verbose),
keda.WithDeployerDecorator(deployDecorator{}),
keda.WithDeployerDecorator(deployDecorator{k8sClient: kc}),
}

return keda.NewDeployer(options...)
return keda.NewDeployer(kc, options...)
}

type deployDecorator struct {
oshDec k8s.OpenshiftMetadataDecorator
k8sClient *k8s.Client
oshDec k8s.OpenshiftMetadataDecorator
}

func (d deployDecorator) UpdateAnnotations(function fn.Function, annotations map[string]string) map[string]string {
if k8s.IsOpenShift() {
if d.k8sClient != nil && d.k8sClient.IsOpenshift() {
return d.oshDec.UpdateAnnotations(function, annotations)
}
return annotations
}

func (d deployDecorator) UpdateLabels(function fn.Function, labels map[string]string) map[string]string {
if k8s.IsOpenShift() {
if d.k8sClient != nil && d.k8sClient.IsOpenshift() {
return d.oshDec.UpdateLabels(function, labels)
}
return labels
Expand Down
5 changes: 3 additions & 2 deletions cmd/completion_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import (
)

func CompleteFunctionList(cmd *cobra.Command, args []string, toComplete string) (strings []string, directive cobra.ShellCompDirective) {
kc := k8s.NewClient(k8s.BuildClientConfig("", "", fn.Local{}))
listers := []fn.Lister{
knative.NewLister(false),
k8s.NewLister(false),
knative.NewLister(kc, false),
k8s.NewLister(kc, false),
}

items := []fn.ListItem{}
Expand Down
7 changes: 5 additions & 2 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"knative.dev/func/cmd/common"
"knative.dev/func/pkg/config"
fn "knative.dev/func/pkg/functions"
"knative.dev/func/pkg/k8s"
)

func NewConfigCmd(
Expand Down Expand Up @@ -89,14 +90,16 @@ func runConfigCmd(cmd *cobra.Command, args []string) (err error) {
if err != nil {
return
}
// construct k8s client for some commands do cluster search
kc := k8s.NewClient(k8s.BuildClientConfig(function.Deploy.Cluster, "", function.Local))

switch answers.SelectedOperation {
case "Add":
switch answers.SelectedConfig {
case "Volumes":
err = runAddVolumesPrompt(cmd.Context(), function)
err = runAddVolumesPrompt(cmd.Context(), kc, function)
case "Environment variables":
err = runAddEnvsPrompt(cmd.Context(), function)
err = runAddEnvsPrompt(cmd.Context(), kc, function)
case "Labels":
err = runAddLabelsPrompt(cmd.Context(), function, common.DefaultLoaderSaver)
case "Git":
Expand Down
9 changes: 5 additions & 4 deletions cmd/config_envs.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ set environment variable from a secret
return loadSaver.Save(function)
}

return runAddEnvsPrompt(cmd.Context(), function)
kc := k8s.NewClient(k8s.BuildClientConfig(function.Deploy.Cluster, "", function.Local))
return runAddEnvsPrompt(cmd.Context(), kc, function)
},
}

Expand Down Expand Up @@ -211,7 +212,7 @@ func listEnvs(f fn.Function, w io.Writer, outputFormat Format) error {
}
}

func runAddEnvsPrompt(ctx context.Context, f fn.Function) (err error) {
func runAddEnvsPrompt(ctx context.Context, kc *k8s.Client, f fn.Function) (err error) {

insertToIndex := 0

Expand Down Expand Up @@ -243,11 +244,11 @@ func runAddEnvsPrompt(ctx context.Context, f fn.Function) (err error) {
}

// SECTION - select the type of Environment variable to be added
secrets, err := k8s.ListSecretsNamesIfConnected(ctx, f.Deploy.Namespace)
secrets, err := k8s.ListSecretsNamesIfConnected(ctx, kc, f.Deploy.Namespace)
if err != nil {
return
}
configMaps, err := k8s.ListConfigMapsNamesIfConnected(ctx, f.Deploy.Namespace)
configMaps, err := k8s.ListConfigMapsNamesIfConnected(ctx, kc, f.Deploy.Namespace)
if err != nil {
return
}
Expand Down
11 changes: 6 additions & 5 deletions cmd/config_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ For non-interactive usage, use flags to specify the volume type and configuratio
}

// Fall back to interactive mode
return runAddVolumesPrompt(cmd.Context(), function)
kc := k8s.NewClient(k8s.BuildClientConfig(function.Deploy.Cluster, "", function.Local))
return runAddVolumesPrompt(cmd.Context(), kc, function)
},
}

Expand Down Expand Up @@ -164,17 +165,17 @@ func listVolumes(f fn.Function) {
}
}

func runAddVolumesPrompt(ctx context.Context, f fn.Function) (err error) {
func runAddVolumesPrompt(ctx context.Context, kc *k8s.Client, f fn.Function) (err error) {

secrets, err := k8s.ListSecretsNamesIfConnected(ctx, f.Deploy.Namespace)
secrets, err := k8s.ListSecretsNamesIfConnected(ctx, kc, f.Deploy.Namespace)
if err != nil {
return
}
configMaps, err := k8s.ListConfigMapsNamesIfConnected(ctx, f.Deploy.Namespace)
configMaps, err := k8s.ListConfigMapsNamesIfConnected(ctx, kc, f.Deploy.Namespace)
if err != nil {
return
}
persistentVolumeClaims, err := k8s.ListPersistentVolumeClaimsNamesIfConnected(ctx, f.Deploy.Namespace)
persistentVolumeClaims, err := k8s.ListPersistentVolumeClaimsNamesIfConnected(ctx, kc, f.Deploy.Namespace)
if err != nil {
return
}
Expand Down
Loading
Loading