nicolaferraro closed pull request #317: Option to create an Integration Context from an existing image URL: https://github.com/apache/camel-k/pull/317
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/pkg/apis/camel/v1alpha1/integrationcontext_types.go b/pkg/apis/camel/v1alpha1/integrationcontext_types.go index b85aa053..038da035 100644 --- a/pkg/apis/camel/v1alpha1/integrationcontext_types.go +++ b/pkg/apis/camel/v1alpha1/integrationcontext_types.go @@ -8,6 +8,7 @@ import ( // IntegrationContextSpec defines the desired state of IntegrationContext type IntegrationContextSpec struct { + Image string `json:"image,omitempty"` Dependencies []string `json:"dependencies,omitempty"` Profile TraitProfile `json:"profile,omitempty"` Traits map[string]IntegrationTraitSpec `json:"traits,omitempty"` @@ -55,6 +56,12 @@ const ( // IntegrationContextTypePlatform -- IntegrationContextTypePlatform = "platform" + // IntegrationContextTypeUser -- + IntegrationContextTypeUser = "user" + + // IntegrationContextTypeExternal -- + IntegrationContextTypeExternal = "external" + // IntegrationContextPhaseBuilding -- IntegrationContextPhaseBuilding IntegrationContextPhase = "Building" // IntegrationContextPhaseReady -- diff --git a/pkg/cmd/completion_bash.go b/pkg/cmd/completion_bash.go index 115f18e3..3d7d5a77 100644 --- a/pkg/cmd/completion_bash.go +++ b/pkg/cmd/completion_bash.go @@ -132,13 +132,14 @@ __kamel_kubectl_get_integrationcontexts() { fi } -__kamel_kubectl_get_user_integrationcontexts() { +__kamel_kubectl_get_non_platform_integrationcontexts() { local template local kubectl_out template="{{ range .items }}{{ .metadata.name }} {{ end }}" + label_condition="camel.apache.org/context.type!=platform" - if kubectl_out=$(kubectl get -l camel.apache.org/context.type=user -o template --template="${template}" integrationcontexts 2>/dev/null); then + if kubectl_out=$(kubectl get -l ${label_condition} -o template --template="${template}" integrationcontexts 2>/dev/null); then COMPREPLY=( $( compgen -W "${kubectl_out}" -- "$cur" ) ) fi } @@ -160,7 +161,7 @@ __custom_func() { return ;; kamel_context_delete) - __kamel_kubectl_get_user_integrationcontexts + __kamel_kubectl_get_non_platform_integrationcontexts return ;; *) @@ -215,7 +216,7 @@ func configureKnownBashCompletions(command *cobra.Command) { command, "context", map[string][]string{ - cobra.BashCompCustom: {"__kamel_kubectl_get_user_integrationcontexts"}, + cobra.BashCompCustom: {"__kamel_kubectl_get_non_platform_integrationcontexts"}, }, ) configureBashAnnotationForFlag( diff --git a/pkg/cmd/context_create.go b/pkg/cmd/context_create.go index 7090d9b8..5463f75b 100644 --- a/pkg/cmd/context_create.go +++ b/pkg/cmd/context_create.go @@ -23,6 +23,8 @@ import ( "strconv" "strings" + "github.com/apache/camel-k/pkg/trait" + "github.com/apache/camel-k/pkg/util" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" @@ -48,11 +50,13 @@ func newContextCreateCmd(rootCmdOptions *RootCmdOptions) *cobra.Command { } cmd.Flags().StringVarP(&impl.runtime, "runtime", "r", "jvm", "Runtime provided by the context") + cmd.Flags().StringVar(&impl.image, "image", "", "Image used to create the context") cmd.Flags().StringSliceVarP(&impl.dependencies, "dependency", "d", nil, "Add a dependency") cmd.Flags().StringSliceVarP(&impl.properties, "property", "p", nil, "Add a camel property") cmd.Flags().StringSliceVar(&impl.configmaps, "configmap", nil, "Add a ConfigMap") cmd.Flags().StringSliceVar(&impl.secrets, "secret", nil, "Add a Secret") - cmd.Flags().StringSliceVar(&impl.Repositories, "repository", nil, "Add a maven repository") + cmd.Flags().StringSliceVar(&impl.repositories, "repository", nil, "Add a maven repository") + cmd.Flags().StringSliceVarP(&impl.traits, "trait", "t", nil, "Configure a trait. E.g. \"-t service.enabled=false\"") // completion support configureKnownCompletions(&cmd) @@ -64,11 +68,13 @@ type contextCreateCommand struct { *RootCmdOptions runtime string + image string dependencies []string properties []string configmaps []string secrets []string - Repositories []string + repositories []string + traits []string } func (command *contextCreateCommand) validateArgs(cmd *cobra.Command, args []string) error { @@ -84,6 +90,18 @@ func (command *contextCreateCommand) run(cmd *cobra.Command, args []string) erro if err != nil { return err } + + catalog := trait.NewCatalog(command.Context, c) + tp := catalog.ComputeTraitsProperties() + for _, t := range command.traits { + kv := strings.SplitN(t, "=", 2) + + if !util.StringSliceExists(tp, kv[0]) { + fmt.Printf("Error: %s is not a valid trait property\n", t) + return nil + } + } + ctx := v1alpha1.NewIntegrationContext(command.Namespace, args[0]) key := k8sclient.ObjectKey{ Namespace: command.Namespace, @@ -101,14 +119,27 @@ func (command *contextCreateCommand) run(cmd *cobra.Command, args []string) erro ctx = v1alpha1.NewIntegrationContext(command.Namespace, kubernetes.SanitizeName(args[0])) ctx.Labels = map[string]string{ - "camel.apache.org/context.type": "user", + "camel.apache.org/context.type": v1alpha1.IntegrationContextTypeUser, } ctx.Spec = v1alpha1.IntegrationContextSpec{ Dependencies: make([]string, 0, len(command.dependencies)), Configuration: make([]v1alpha1.ConfigurationSpec, 0), - Repositories: command.Repositories, + Repositories: command.repositories, } + if command.image != "" { + // + // if the image is set, the context do not require any build but + // is be marked as external as the information about the classpath + // is missing so it cannot be used as base for other contexts + // + ctx.Labels["camel.apache.org/context.type"] = v1alpha1.IntegrationContextTypeExternal + + // + // Set the image to be used by the context + // + ctx.Spec.Image = command.image + } for _, item := range command.dependencies { switch { case strings.HasPrefix(item, "mvn:"): @@ -145,6 +176,11 @@ func (command *contextCreateCommand) run(cmd *cobra.Command, args []string) erro Value: item, }) } + for _, item := range command.traits { + if err := command.configureTrait(&ctx, item); err != nil { + return nil + } + } existed := false err = c.Create(command.Context, &ctx) @@ -173,3 +209,28 @@ func (command *contextCreateCommand) run(cmd *cobra.Command, args []string) erro return nil } + +func (*contextCreateCommand) configureTrait(ctx *v1alpha1.IntegrationContext, config string) error { + if ctx.Spec.Traits == nil { + ctx.Spec.Traits = make(map[string]v1alpha1.IntegrationTraitSpec) + } + + parts := traitConfigRegexp.FindStringSubmatch(config) + if len(parts) < 4 { + return errors.New("unrecognized config format (expected \"<trait>.<prop>=<val>\"): " + config) + } + traitID := parts[1] + prop := parts[2][1:] + val := parts[3] + + spec, ok := ctx.Spec.Traits[traitID] + if !ok { + spec = v1alpha1.IntegrationTraitSpec{ + Configuration: make(map[string]string), + } + } + + spec.Configuration[prop] = val + ctx.Spec.Traits[traitID] = spec + return nil +} diff --git a/pkg/cmd/context_get.go b/pkg/cmd/context_get.go index 3fdab174..a0d88b10 100644 --- a/pkg/cmd/context_get.go +++ b/pkg/cmd/context_get.go @@ -49,7 +49,8 @@ func newContextGetCmd(rootCmdOptions *RootCmdOptions) *cobra.Command { }, } - cmd.Flags().BoolVar(&impl.user, "user", true, "Includes user contexts") + cmd.Flags().BoolVar(&impl.user, v1alpha1.IntegrationContextTypeUser, true, "Includes user contexts") + cmd.Flags().BoolVar(&impl.external, v1alpha1.IntegrationContextTypeExternal, true, "Includes external contexts") cmd.Flags().BoolVar(&impl.platform, v1alpha1.IntegrationContextTypePlatform, true, "Includes platform contexts") return &cmd @@ -58,6 +59,7 @@ func newContextGetCmd(rootCmdOptions *RootCmdOptions) *cobra.Command { type contextGetCommand struct { *RootCmdOptions user bool + external bool platform bool } @@ -80,10 +82,11 @@ func (command *contextGetCommand) run() error { fmt.Fprintln(w, "NAME\tPHASE\tTYPE\tIMAGE") for _, ctx := range ctxList.Items { t := ctx.Labels["camel.apache.org/context.type"] - u := command.user && t == "user" + u := command.user && t == v1alpha1.IntegrationContextTypeUser + e := command.external && t == v1alpha1.IntegrationContextTypeExternal p := command.platform && t == v1alpha1.IntegrationContextTypePlatform - if u || p { + if u || e || p { fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", ctx.Name, string(ctx.Status.Phase), t, ctx.Status.Image) } } diff --git a/pkg/controller/integrationcontext/initialize.go b/pkg/controller/integrationcontext/initialize.go index 20302acd..80b9452a 100644 --- a/pkg/controller/integrationcontext/initialize.go +++ b/pkg/controller/integrationcontext/initialize.go @@ -52,15 +52,19 @@ func (action *initializeAction) Handle(ctx context.Context, ictx *v1alpha1.Integ target := ictx.DeepCopy() - // execute custom initialization - //if err := trait.apply(nil, context); err != nil { - // return err - //} - - // update the status - logrus.Info("Context ", target.Name, " transitioning to state ", v1alpha1.IntegrationContextPhaseBuilding) + // by default the context should be build target.Status.Phase = v1alpha1.IntegrationContextPhaseBuilding - dgst, err := digest.ComputeForIntegrationContext(ictx) + + if target.Spec.Image != "" { + // but in case it has been created from an image, mark the + // context as ready + target.Status.Phase = v1alpha1.IntegrationContextPhaseReady + + // and set the image to be used + target.Status.Image = target.Spec.Image + } + + dgst, err := digest.ComputeForIntegrationContext(target) if err != nil { return err } diff --git a/pkg/trait/classpath.go b/pkg/trait/classpath.go index 2eec71a9..ff50440a 100644 --- a/pkg/trait/classpath.go +++ b/pkg/trait/classpath.go @@ -81,6 +81,15 @@ func (t *classpathTrait) Apply(e *Environment) error { deps = append(deps, artifact.Target) } + if e.Context.Labels["camel.apache.org/context.type"] == v1alpha1.IntegrationContextTypeExternal { + // + // In case of an external created context. we do not have any information about + // the classpath so we assume the all jars in /deployments/dependencies/ have + // to be taken into account + // + deps = append(deps, "/deployments/dependencies/*") + } + envvar.SetVal(&e.EnvVars, "JAVA_CLASSPATH", strings.Join(deps, ":")) return nil diff --git a/pkg/trait/springboot.go b/pkg/trait/springboot.go index 7c790e53..325a8673 100644 --- a/pkg/trait/springboot.go +++ b/pkg/trait/springboot.go @@ -78,7 +78,6 @@ func (t *springBootTrait) Apply(e *Environment) error { // Override env vars envvar.SetVal(&e.EnvVars, "JAVA_MAIN_CLASS", "org.springframework.boot.loader.PropertiesLauncher") - envvar.SetVal(&e.EnvVars, "LOADER_PATH", "/deployments/dependencies/") deps := make([]string, 0, 2+len(e.Context.Status.Artifacts)) deps = append(deps, "/etc/camel/resources") @@ -97,6 +96,15 @@ func (t *springBootTrait) Apply(e *Environment) error { deps = append(deps, artifact.Target) } + if e.Context.Labels["camel.apache.org/context.type"] == v1alpha1.IntegrationContextTypeExternal { + // + // In case of an external created context. we do not have any information about + // the classpath so we assume the all jars in /deployments/dependencies/ have + // to be taken into account + // + deps = append(deps, "/deployments/dependencies/") + } + envvar.SetVal(&e.EnvVars, "LOADER_HOME", "/deployments") envvar.SetVal(&e.EnvVars, "LOADER_PATH", strings.Join(deps, ",")) } ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services