This is an automated email from the ASF dual-hosted git repository. squakez pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit abe7b82ebded4a6b6274e2a93a45fc38d9b0f4a8 Author: Suhail Hany <[email protected]> AuthorDate: Sat Sep 19 13:48:52 2026 +0300 Fix #6829: drop support for kamel run --dev/--sync Both flags were deprecated in v2.9.0. Removes the flags, the runCmdOptions fields behind them, and the code that existed only to serve them: syncIntegration, filterFileLocation, the pkg/util/sync package and DeleteIntegration. --logs and --wait keep their current behaviour. --- .../ROOT/pages/configuration/dependencies.adoc | 2 +- pkg/cmd/run.go | 125 +-------------------- pkg/cmd/run_support.go | 12 -- pkg/cmd/run_support_test.go | 17 --- pkg/cmd/run_test.go | 26 ----- pkg/cmd/util.go | 12 -- pkg/util/sync/file.go | 56 --------- pkg/util/sync/file_test.go | 68 ----------- 8 files changed, 6 insertions(+), 312 deletions(-) diff --git a/docs/modules/ROOT/pages/configuration/dependencies.adoc b/docs/modules/ROOT/pages/configuration/dependencies.adoc index c02c00fa4..c46699682 100644 --- a/docs/modules/ROOT/pages/configuration/dependencies.adoc +++ b/docs/modules/ROOT/pages/configuration/dependencies.adoc @@ -11,7 +11,7 @@ from("imap://[email protected]") Since the integration has a endpoint starting with the **"imap:" prefix**, Camel K is able to **automatically add the "camel-mail" component** to the list of required dependencies. The `seda:` endpoint belongs to `camel-core` that is automatically added to all integrations, so Camel K will not add additional dependencies for it. This dependency resolution mechanism is transparent to the user, that will just see the integration running. -Automatic resolution is also a nice feature in _dev mode_, because you are allowed to add all components you need *without exiting the dev loop*. +Automatic resolution is also a nice feature while you iterate on an integration, because you are allowed to add all components you need *without editing the list of dependencies by hand*. NOTE: Camel K won't be able to resolve automatically the dependencies when your routes specify dynamic URIs. diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index 877d4d070..cd0ae229e 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -24,12 +24,10 @@ import ( "fmt" "net/url" "os" - "os/signal" "path" "reflect" "strconv" "strings" - "syscall" "github.com/magiconair/properties" @@ -54,7 +52,6 @@ import ( k8slog "github.com/apache/camel-k/v2/pkg/util/kubernetes/log" "github.com/apache/camel-k/v2/pkg/util/property" "github.com/apache/camel-k/v2/pkg/util/resource" - "github.com/apache/camel-k/v2/pkg/util/sync" "github.com/apache/camel-k/v2/pkg/util/watch" ) @@ -93,8 +90,6 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions) "key optionally represents the configmap/secret key to be filtered and path represents the destination path)") cmd.Flags().StringArray("maven-repository", nil, "Add a maven repository") cmd.Flags().Bool("logs", false, "Print integration logs") - cmd.Flags().Bool("sync", false, "[Deprecated] Synchronize the local source file with the cluster, republishing at each change") - cmd.Flags().Bool("dev", false, "[Deprecated] Enable Dev mode (equivalent to \"-w --logs --sync\")") cmd.Flags().Bool("use-flows", true, "Write yaml sources as Flow objects in the integration custom resource") cmd.Flags().StringP("operator-id", "x", "", "Operator id selected to manage this integration.") cmd.Flags().String("profile", "", "Trait profile used for deployment") @@ -129,12 +124,8 @@ type runCmdOptions struct { Compression bool `mapstructure:"compression" yaml:",omitempty"` Wait bool `mapstructure:"wait" yaml:",omitempty"` Logs bool `mapstructure:"logs" yaml:",omitempty"` - // Deprecated: won't be supported in the future - Sync bool `mapstructure:"sync" yaml:",omitempty"` - // Deprecated: won't be supported in the future - Dev bool `mapstructure:"dev" yaml:",omitempty"` - UseFlows bool `mapstructure:"use-flows" yaml:",omitempty"` - Save bool `kamel:"omitsave" mapstructure:"save" yaml:",omitempty"` + UseFlows bool `mapstructure:"use-flows" yaml:",omitempty"` + Save bool `kamel:"omitsave" mapstructure:"save" yaml:",omitempty"` // Deprecated: won't be supported in the future IntegrationKit string `mapstructure:"kit" yaml:",omitempty"` IntegrationName string `mapstructure:"name" yaml:",omitempty"` @@ -259,10 +250,6 @@ func (o *runCmdOptions) validate(cmd *cobra.Command) error { return err } - if o.OutputFormat != "" && o.Dev { - return errors.New("cannot use --dev with -o/--output option") - } - for _, label := range o.Labels { parts := strings.Split(label, "=") if len(parts) != 2 { @@ -299,11 +286,6 @@ func (o *runCmdOptions) validate(cmd *cobra.Command) error { fmt.Fprintf(cmd.OutOrStdout(), "Compression property is deprecated. It will be removed from future releases.\n") } - // Deprecated: to be removed - if o.Sync || o.Dev { - fmt.Fprintf(cmd.OutOrStdout(), "Dev and Sync properties are deprecated. They will be removed from future releases.\n") - } - var client client.Client if !isOfflineCommand(cmd) { client, err = o.GetCmdClient() @@ -348,32 +330,7 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error { return err } - if o.Dev { - cs := make(chan os.Signal, 1) - signal.Notify(cs, os.Interrupt, syscall.SIGTERM) - go func() { - <-cs - if o.Context.Err() != nil { - // Context canceled - return - } - fmt.Fprintln(cmd.OutOrStdout(), "Run integration terminating") - err := DeleteIntegration(o.Context, c, integration.Name, integration.Namespace) - if err != nil { - fmt.Fprintln(cmd.ErrOrStderr(), err) - os.Exit(1) - } - os.Exit(0) - }() - } - - if o.Sync || o.Dev { - err = o.syncIntegration(cmd, c, args) - if err != nil { - return err - } - } - if o.Logs || o.Dev || o.Wait { + if o.Logs || o.Wait { //nolint:errcheck go watch.HandleIntegrationEvents(o.Context, c, integration, func(event *corev1.Event) bool { fmt.Fprintln(cmd.OutOrStdout(), event.Message) @@ -381,7 +338,7 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error { return true }) } - if o.Wait || o.Dev { + if o.Wait { phase := v1.IntegrationPhaseRunning if o.DontRunAfterBuild { phase = v1.IntegrationPhaseBuildComplete @@ -409,14 +366,11 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error { integration.ResourceVersion = existing.ResourceVersion } } - if o.Logs || o.Dev { + if o.Logs { err = k8slog.Print(o.Context, cmd, c, integration, nil, cmd.OutOrStdout()) if err != nil { return err } - } - - if o.Sync || o.Logs || o.Dev { // Let's add a Wait point, otherwise the script terminates <-o.RootContext.Done() } @@ -467,75 +421,6 @@ func (o *runCmdOptions) waitForIntegrationPhase(cmd *cobra.Command, c client.Cli return watch.HandleIntegrationStateChanges(o.Context, c, integration, handler) } -func (o *runCmdOptions) syncIntegration(cmd *cobra.Command, c client.Client, sources []string) error { - // Let's watch all relevant files when in dev mode - res := filterFileLocation(o.Resources) - cfg := filterFileLocation(o.Configs) - prop := filterFileLocation(o.Properties) - buildProp := filterFileLocation(o.BuildProperties) - - files := make([]string, 0, - len(sources)+len(res)+len(cfg)+len(prop)+len(buildProp), - ) - - files = append(files, sources...) - files = append(files, res...) - files = append(files, cfg...) - files = append(files, prop...) - files = append(files, buildProp...) - - for _, s := range files { - ok, err := source.IsLocalAndFileExists(s) - if err != nil { - return err - } - if ok { - changes, err := sync.File(o.Context, s) - if err != nil { - return err - } - go func() { - for { - select { - case <-o.Context.Done(): - return - case <-changes: - // let's create a new command to parse modeline changes and update our integration - newCmd, _, err := createKamelWithModelineCommand(o.RootContext, os.Args[1:]) - newCmd.SetOut(cmd.OutOrStdout()) - newCmd.SetErr(cmd.ErrOrStderr()) - if err != nil { - fmt.Fprintln(newCmd.ErrOrStderr(), "Unable to sync integration: ", err.Error()) - - continue - } - newCmd.Args = o.validateArgs - newCmd.PreRunE = o.decode - newCmd.RunE = func(cmd *cobra.Command, args []string) error { - _, err := o.createOrUpdateIntegration(cmd, c, sources) - - return err - } - newCmd.PostRunE = nil - - // cancel the existing command to release watchers - o.ContextCancel() - // run the new one - err = newCmd.Execute() - if err != nil { - fmt.Fprintln(newCmd.ErrOrStderr(), "Unable to sync integration: ", err.Error()) - } - } - } - }() - } else { - fmt.Fprintf(cmd.ErrOrStderr(), "Warning: the following URL will not be watched for changes: %s\n", s) - } - } - - return nil -} - func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.Client, sources []string) (*v1.Integration, error) { namespace := o.Namespace name, err := o.GetIntegrationName(sources) diff --git a/pkg/cmd/run_support.go b/pkg/cmd/run_support.go index acc35e58c..4ee28c9a8 100644 --- a/pkg/cmd/run_support.go +++ b/pkg/cmd/run_support.go @@ -64,18 +64,6 @@ func parseConfig(ctx context.Context, cmd *cobra.Command, c client.Client, confi return nil } -func filterFileLocation(maybeFileLocations []string) []string { - filteredOptions := make([]string, 0) - for _, option := range maybeFileLocations { - if strings.HasPrefix(option, "file:") { - localPath, _ := resource.ParseFileValue(strings.Replace(option, "file:", "", 1)) - filteredOptions = append(filteredOptions, localPath) - } - } - - return filteredOptions -} - func keyValueProps(value string) (*properties.Properties, error) { return properties.Load([]byte(value), properties.UTF8) } diff --git a/pkg/cmd/run_support_test.go b/pkg/cmd/run_support_test.go index 81d208855..9afd8d50f 100644 --- a/pkg/cmd/run_support_test.go +++ b/pkg/cmd/run_support_test.go @@ -23,23 +23,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestFilterFileLocation(t *testing.T) { - optionFileLocations := []string{ - "file:/path/to/valid/file", - "file:app.properties", - "configmap:my-configmap", - "secret:my-secret", - "file:/validfile@/tmp/destination", - } - - filteredOptions := filterFileLocation(optionFileLocations) - - assert.Equal(t, 3, len(filteredOptions)) - assert.Equal(t, "/path/to/valid/file", filteredOptions[0]) - assert.Equal(t, "app.properties", filteredOptions[1]) - assert.Equal(t, "/validfile", filteredOptions[2]) -} - func TestExtractTraitNames(t *testing.T) { traitProps := []string{"container.enabled=true", "no-trait.noval=1", "nothing"} tn := extractTraitNames(traitProps) diff --git a/pkg/cmd/run_test.go b/pkg/cmd/run_test.go index a811ac6b8..98dabb531 100644 --- a/pkg/cmd/run_test.go +++ b/pkg/cmd/run_test.go @@ -105,8 +105,6 @@ func TestRunNoFlag(t *testing.T) { // Check default expected values assert.False(t, runCmdOptions.Wait) assert.False(t, runCmdOptions.Logs) - assert.False(t, runCmdOptions.Sync) - assert.False(t, runCmdOptions.Dev) assert.True(t, runCmdOptions.UseFlows) assert.False(t, runCmdOptions.Compression) assert.False(t, runCmdOptions.Save) @@ -139,23 +137,6 @@ func TestRunDependencyFlag(t *testing.T) { assert.Equal(t, "dependency3", runCmdOptions.Dependencies[2]) } -func TestRunDevFlag(t *testing.T) { - runCmdOptions, rootCmd, _ := initializeRunCmdOptions(t) - _, err := ExecuteCommand(rootCmd, cmdRun, "--dev", integrationSource) - require.NoError(t, err) - assert.True(t, runCmdOptions.Dev) -} - -func TestRunDevModeOutputFlag(t *testing.T) { - runCmdOptions, rootCmd, _ := initializeRunCmdOptions(t) - _, err := ExecuteCommand(rootCmd, cmdRun, "--dev", "-o", "yaml", integrationSource) - assert.True(t, runCmdOptions.Dev) - assert.Equal(t, "yaml", runCmdOptions.OutputFormat) - require.Error(t, err) - assert.Equal(t, "cannot use --dev with -o/--output option", - err.Error()) -} - func TestRunEnvFlag(t *testing.T) { runCmdOptions, rootCmd, _ := initializeRunCmdOptions(t) _, err := ExecuteCommand(rootCmd, cmdRun, @@ -382,13 +363,6 @@ func TestRunSourceFlag(t *testing.T) { assert.Equal(t, "source1", runCmdOptions.Sources[0]) } -func TestRunSyncFlag(t *testing.T) { - runCmdOptions, rootCmd, _ := initializeRunCmdOptions(t) - _, err := ExecuteCommand(rootCmd, cmdRun, "--sync", integrationSource) - require.NoError(t, err) - assert.True(t, runCmdOptions.Sync) -} - func TestRunExistingTraitFlag(t *testing.T) { runCmdOptions, rootCmd, _ := initializeRunCmdOptions(t) _, err := ExecuteCommand(rootCmd, cmdRun, diff --git a/pkg/cmd/util.go b/pkg/cmd/util.go index ba5807d8f..cbea754fc 100644 --- a/pkg/cmd/util.go +++ b/pkg/cmd/util.go @@ -43,18 +43,6 @@ const ( offlineCommandLabel = "camel.apache.org/cmd.offline" ) -// DeleteIntegration --. -func DeleteIntegration(ctx context.Context, c client.Client, name string, namespace string) error { - integration := v1.Integration{ - Kind: v1.IntegrationKind, - APIVersion: v1.SchemeGroupVersion.String(), - Namespace: namespace, - Name: name, - } - - return c.Delete(ctx, &integration) -} - func bindPFlagsHierarchy(cmd *cobra.Command, v *viper.Viper) error { for _, c := range cmd.Commands() { if err := bindPFlags(c, v); err != nil { diff --git a/pkg/util/sync/file.go b/pkg/util/sync/file.go deleted file mode 100644 index bb9aee226..000000000 --- a/pkg/util/sync/file.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package sync provides useful tools to get notified when a file system resource changes -package sync - -import ( - "context" - - "github.com/fsnotify/fsnotify" -) - -// File returns a channel that signals each time the content of the file changes. -func File(ctx context.Context, path string) (<-chan bool, error) { - watcher, err := fsnotify.NewWatcher() - if err != nil { - return nil, err - } - - out := make(chan bool) - - // Start listening for events. - go func() { - for { - select { - case <-ctx.Done(): - return - case event := <-watcher.Events: - if event.Has(fsnotify.Write) { - out <- true - } - } - } - }() - - err = watcher.Add(path) - if err != nil { - return nil, err - } - - return out, nil -} diff --git a/pkg/util/sync/file_test.go b/pkg/util/sync/file_test.go deleted file mode 100644 index 6ae7f1cd7..000000000 --- a/pkg/util/sync/file_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You under the Apache License, Version 2.0 -(the "License"); you may not use this file except in compliance with -the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sync - -import ( - "context" - "os" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestFile(t *testing.T) { - tempDir := t.TempDir() - file, err := os.CreateTemp(tempDir, "camel-k-test-*") - require.NoError(t, err) - defer func() { - _ = os.Remove(file.Name()) - }() - - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(100*time.Second)) - defer cancel() - changes, err := File(ctx, file.Name()) - require.NoError(t, err) - - time.Sleep(100 * time.Millisecond) - expectedNumChanges := 3 - for i := 0; i < expectedNumChanges; i++ { - if err := os.WriteFile(file.Name(), []byte("data-"+strconv.Itoa(i)), 0o600); err != nil { - t.Error(err) - } - time.Sleep(350 * time.Millisecond) - } - - numChanges := 0 -watch: - for { - select { - case <-ctx.Done(): - return - case <-changes: - numChanges++ - if numChanges == expectedNumChanges { - break watch - } - } - } - - assert.Equal(t, expectedNumChanges, numChanges) -}
