func()

in internal/pkg/cli/run_local.go [365:448]


func (o *runLocalOpts) Execute() error {
	if err := o.configureClients(); err != nil {
		return err
	}

	ctx := context.Background()

	task, err := o.prepareTask(ctx)
	if err != nil {
		return err
	}

	var hosts []orchestrator.Host
	var ssmTarget string
	if o.proxy {
		if err := validateMinEnvVersion(o.ws, o.envChecker, o.appName, o.envName, template.RunLocalProxyMinEnvVersion, "run local --proxy"); err != nil {
			return err
		}

		hosts, err = o.hostFinder.Hosts(ctx)
		if err != nil {
			return fmt.Errorf("find hosts to connect to: %w", err)
		}

		ssmTarget, err = o.getSSMTarget(ctx)
		if err != nil {
			return fmt.Errorf("get proxy target container: %w", err)
		}
	}

	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

	errCh := o.orchestrator.Start()
	var runTaskOpts []orchestrator.RunTaskOption
	if o.proxy {
		runTaskOpts = append(runTaskOpts, orchestrator.RunTaskWithProxy(ssmTarget, o.proxyNetwork, hosts...))
	}
	o.orchestrator.RunTask(task, runTaskOpts...)

	var watchCh <-chan interface{}
	var watchErrCh <-chan error
	stopCh := make(chan struct{})
	if o.watch {
		watchCh, watchErrCh, err = o.watchLocalFiles(stopCh)
		if err != nil {
			return fmt.Errorf("setup watch: %s", err)
		}
	}

	for {
		select {
		case err, ok := <-errCh:
			// we loop until errCh closes, since Start()
			// closes errCh when the orchestrator is completely done.
			if !ok {
				close(stopCh)
				return nil
			}

			log.Errorf("error: %s\n", err)
			o.orchestrator.Stop()
		case <-sigCh:
			signal.Stop(sigCh)
			o.orchestrator.Stop()
		case <-watchErrCh:
			log.Errorf("watch: %s\n", err)
			o.orchestrator.Stop()
		case <-watchCh:
			task, err = o.prepareTask(ctx)
			if err != nil {
				log.Errorf("rerun task: %s\n", err)
				o.orchestrator.Stop()
				break
			}

			// If TaskRole is retrieved through ECS Exec, OS signals are no longer provided to the channel.
			// We reset this channel connection through this call as a short term fix that allows
			// the interrupt and terminate signal to stop tasks after the task has been restarted by --watch.
			signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
			o.orchestrator.RunTask(task)
		}
	}
}