You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2026/09/22 09:39:00 UTC

(camel-k) 01/04: Fix #6829: drop support for kamel run --dev/--sync

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 <su...@gmail.com>
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://admin@myserver.com")
 
 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)
-}