Unverified Commit 20b9ba12 authored by Cristian Maglie's avatar Cristian Maglie Committed by GitHub

[skip-changelog] Moved discovery client implementation into his own library (#2531)


* Moved discovery client implementation into his own library

* Updated to latest release of pluggable-discovery-protocol-handler lib
parent 31e44786
......@@ -31,11 +31,11 @@ import (
"github.com/arduino/arduino-cli/commands/internal/instances"
"github.com/arduino/arduino-cli/internal/arduino/cores"
"github.com/arduino/arduino-cli/internal/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/internal/arduino/discovery"
"github.com/arduino/arduino-cli/internal/arduino/httpclient"
"github.com/arduino/arduino-cli/internal/inventory"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/arduino/go-properties-orderedmap"
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
"github.com/sirupsen/logrus"
)
......@@ -234,7 +234,7 @@ func List(req *rpc.BoardListRequest) (r []*rpc.DetectedPort, discoveryStartError
// boards slice can be empty at this point if neither the cores nor the
// API managed to recognize the connected board
b := &rpc.DetectedPort{
Port: port.ToRPC(),
Port: rpc.DiscoveryPortToRPC(port),
MatchingBoards: boards,
}
......@@ -283,7 +283,7 @@ func Watch(ctx context.Context, req *rpc.BoardListWatchRequest) (<-chan *rpc.Boa
defer close(outChan)
for event := range watcher.Feed() {
port := &rpc.DetectedPort{
Port: event.Port.ToRPC(),
Port: rpc.DiscoveryPortToRPC(event.Port),
}
boardsError := ""
......
......@@ -22,10 +22,10 @@ import (
"testing"
"github.com/arduino/arduino-cli/internal/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/internal/arduino/discovery"
"github.com/arduino/arduino-cli/internal/cli/configuration"
"github.com/arduino/go-paths-helper"
"github.com/arduino/go-properties-orderedmap"
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
"github.com/stretchr/testify/require"
semver "go.bug.st/relaxed-semver"
)
......
......@@ -29,7 +29,6 @@ import (
f "github.com/arduino/arduino-cli/internal/algorithms"
"github.com/arduino/arduino-cli/internal/arduino/cores"
"github.com/arduino/arduino-cli/internal/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/internal/arduino/discovery"
"github.com/arduino/arduino-cli/internal/arduino/globals"
"github.com/arduino/arduino-cli/internal/arduino/sketch"
"github.com/arduino/arduino-cli/internal/i18n"
......@@ -37,6 +36,7 @@ import (
paths "github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
serialutils "github.com/arduino/go-serial-utils"
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
"github.com/sirupsen/logrus"
)
......@@ -209,7 +209,7 @@ func runProgramAction(pme *packagemanager.Explorer,
outStream, errStream io.Writer,
dryRun bool, userFields map[string]string,
) (*rpc.Port, error) {
port := discovery.PortFromRPCPort(userPort)
port := rpc.DiscoveryPortFromRPCPort(userPort)
if port == nil || (port.Address == "" && port.Protocol == "") {
// For no-port uploads use "default" protocol
port = &discovery.Port{Protocol: "default"}
......@@ -528,7 +528,7 @@ func runProgramAction(pme *packagemanager.Explorer,
// If the algorithms can not detect the new port, fallback to the user-provided port.
return userPort, nil
}
return updatedPort.ToRPC(), nil
return rpc.DiscoveryPortToRPC(updatedPort), nil
}
func detectUploadPort(
......
......@@ -24,7 +24,6 @@ import (
"github.com/arduino/arduino-cli/commands/cmderrors"
"github.com/arduino/arduino-cli/internal/arduino/cores"
"github.com/arduino/arduino-cli/internal/arduino/discovery"
"github.com/arduino/arduino-cli/internal/cli/configuration"
"github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap"
......@@ -636,8 +635,7 @@ func (pme *Explorer) loadDiscovery(id string) error {
return errors.New(tr("discovery %s not installed", id))
}
discoveryPath := toolRelease.InstallDir.Join(tool.Name).String()
d := discovery.New(id, discoveryPath)
pme.discoveryManager.Add(d)
pme.discoveryManager.Add(id, discoveryPath)
return nil
}
......@@ -713,8 +711,7 @@ func (pme *Explorer) loadDiscoveries(release *cores.PlatformRelease) []error {
if cmdArgs, err := properties.SplitQuotedString(cmd, `"'`, true); err != nil {
merr = append(merr, err)
} else {
d := discovery.New(discoveryID, cmdArgs...)
pme.discoveryManager.Add(d)
pme.discoveryManager.Add(discoveryID, cmdArgs...)
}
}
......
This diff is collapsed.
......@@ -22,7 +22,6 @@ import (
"os"
"sort"
"github.com/arduino/arduino-cli/internal/arduino/discovery"
"github.com/arduino/arduino-cli/internal/arduino/discovery/discoverymanager"
"github.com/sirupsen/logrus"
)
......@@ -35,8 +34,7 @@ func main() {
logrus.SetLevel(logrus.ErrorLevel)
dm := discoverymanager.New()
for _, discCmd := range os.Args[1:] {
disc := discovery.New(discCmd, discCmd)
dm.Add(disc)
dm.Add(discCmd, discCmd)
}
dm.Start()
......
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package discovery
import (
"io"
"testing"
"time"
"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)
func TestDiscoveryStdioHandling(t *testing.T) {
// Build `cat` helper inside testdata/cat
builder, err := paths.NewProcess(nil, "go", "build")
require.NoError(t, err)
builder.SetDir("testdata/cat")
require.NoError(t, builder.Run())
// Run cat and test if streaming json works as expected
disc := New("test", "testdata/cat/cat") // copy stdin to stdout
err = disc.runProcess()
require.NoError(t, err)
_, err = disc.outgoingCommandsPipe.Write([]byte(`{ "eventType":`)) // send partial JSON
require.NoError(t, err)
msg, err := disc.waitMessage(time.Millisecond * 100)
require.Error(t, err)
require.Nil(t, msg)
_, err = disc.outgoingCommandsPipe.Write([]byte(`"ev1" }{ `)) // complete previous json and start another one
require.NoError(t, err)
msg, err = disc.waitMessage(time.Millisecond * 100)
require.NoError(t, err)
require.NotNil(t, msg)
require.Equal(t, "ev1", msg.EventType)
msg, err = disc.waitMessage(time.Millisecond * 100)
require.Error(t, err)
require.Nil(t, msg)
_, err = disc.outgoingCommandsPipe.Write([]byte(`"eventType":"ev2" }`)) // complete previous json
require.NoError(t, err)
msg, err = disc.waitMessage(time.Millisecond * 100)
require.NoError(t, err)
require.NotNil(t, msg)
require.Equal(t, "ev2", msg.EventType)
require.Equal(t, disc.State(), Alive)
err = disc.outgoingCommandsPipe.(io.ReadCloser).Close()
require.NoError(t, err)
time.Sleep(time.Millisecond * 100)
require.Equal(t, disc.State(), Dead)
}
......@@ -21,8 +21,9 @@ import (
"sync"
"time"
"github.com/arduino/arduino-cli/internal/arduino/discovery"
"github.com/arduino/arduino-cli/internal/cli/configuration"
"github.com/arduino/arduino-cli/internal/i18n"
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
"github.com/sirupsen/logrus"
)
......@@ -34,9 +35,9 @@ import (
// is called.
type DiscoveryManager struct {
discoveriesMutex sync.Mutex
discoveries map[string]*discovery.PluggableDiscovery // all registered PluggableDiscovery
discoveriesRunning bool // set to true once discoveries are started
feed chan *discovery.Event // all events will pass through this channel
discoveries map[string]*discovery.Client // all registered PluggableDiscovery
discoveriesRunning bool // set to true once discoveries are started
feed chan *discovery.Event // all events will pass through this channel
watchersMutex sync.Mutex
watchers map[*PortWatcher]bool // all registered Watcher
watchersCache map[string]map[string]*discovery.Event // this is a cache of all active ports
......@@ -47,7 +48,7 @@ var tr = i18n.Tr
// New creates a new DiscoveryManager
func New() *DiscoveryManager {
return &DiscoveryManager{
discoveries: map[string]*discovery.PluggableDiscovery{},
discoveries: map[string]*discovery.Client{},
watchers: map[*PortWatcher]bool{},
feed: make(chan *discovery.Event, 50),
watchersCache: map[string]map[string]*discovery.Event{},
......@@ -65,7 +66,7 @@ func (dm *DiscoveryManager) Clear() {
logrus.Infof("Closed and removed discovery %s", d.GetID())
}
}
dm.discoveries = map[string]*discovery.PluggableDiscovery{}
dm.discoveries = map[string]*discovery.Client{}
}
// IDs returns the list of discoveries' ids in this DiscoveryManager
......@@ -101,7 +102,7 @@ func (dm *DiscoveryManager) Start() []error {
var wg sync.WaitGroup
for _, d := range dm.discoveries {
wg.Add(1)
go func(d *discovery.PluggableDiscovery) {
go func(d *discovery.Client) {
if err := dm.startDiscovery(d); err != nil {
errsLock.Lock()
errs = append(errs, err)
......@@ -117,7 +118,14 @@ func (dm *DiscoveryManager) Start() []error {
}
// Add adds a discovery to the list of managed discoveries
func (dm *DiscoveryManager) Add(d *discovery.PluggableDiscovery) error {
func (dm *DiscoveryManager) Add(id string, args ...string) error {
d := discovery.NewClient(id, args...)
d.SetLogger(logrus.WithField("discovery", id))
d.SetUserAgent(configuration.UserAgent(configuration.Settings))
return dm.add(d)
}
func (dm *DiscoveryManager) add(d *discovery.Client) error {
dm.discoveriesMutex.Lock()
defer dm.discoveriesMutex.Unlock()
......@@ -178,7 +186,7 @@ func (dm *DiscoveryManager) Watch() (*PortWatcher, error) {
return watcher, nil
}
func (dm *DiscoveryManager) startDiscovery(d *discovery.PluggableDiscovery) (discErr error) {
func (dm *DiscoveryManager) startDiscovery(d *discovery.Client) (discErr error) {
defer func() {
// If this function returns an error log it
if discErr != nil {
......@@ -194,7 +202,7 @@ func (dm *DiscoveryManager) startDiscovery(d *discovery.PluggableDiscovery) (dis
return fmt.Errorf("%s: %s", tr("starting discovery %s", d.GetID()), err)
}
go func(d *discovery.PluggableDiscovery) {
go func(d *discovery.Client) {
// Transfer all incoming events from this discovery to the feed channel
for ev := range eventCh {
dm.feed <- ev
......@@ -281,6 +289,6 @@ func (dm *DiscoveryManager) List() []*discovery.Port {
// AddAllDiscoveriesFrom transfers discoveries from src to the receiver
func (dm *DiscoveryManager) AddAllDiscoveriesFrom(src *DiscoveryManager) {
for _, d := range src.discoveries {
dm.Add(d)
dm.add(d)
}
}
// This file is part of arduino-cli.
//
// Copyright 2023 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
// Echo stdin to stdout.
// This program is used for testing purposes, to make it available on all
// OS a tool equivalent to UNIX "cat".
package main
import (
"io"
"os"
)
func main() {
io.Copy(os.Stdout, os.Stdin)
}
......@@ -18,6 +18,8 @@ package commands
import (
"sort"
"github.com/arduino/go-properties-orderedmap"
discovery "github.com/arduino/pluggable-discovery-protocol-handler/v2"
semver "go.bug.st/relaxed-semver"
)
......@@ -98,3 +100,37 @@ func (s *PlatformSummary) GetSortedReleases() []*PlatformRelease {
})
return res
}
// DiscoveryPortToRPC converts a *discovery.Port into an *rpc.Port
func DiscoveryPortToRPC(p *discovery.Port) *Port {
props := p.Properties
if props == nil {
props = properties.NewMap()
}
return &Port{
Address: p.Address,
Label: p.AddressLabel,
Protocol: p.Protocol,
ProtocolLabel: p.ProtocolLabel,
HardwareId: p.HardwareID,
Properties: props.AsMap(),
}
}
// DiscoveryPortFromRPCPort converts an *rpc.Port into a *discovery.Port
func DiscoveryPortFromRPCPort(o *Port) (p *discovery.Port) {
if o == nil {
return nil
}
res := &discovery.Port{
Address: o.GetAddress(),
AddressLabel: o.GetLabel(),
Protocol: o.GetProtocol(),
ProtocolLabel: o.GetProtocolLabel(),
HardwareID: o.GetHardwareId(),
}
if o.GetProperties() != nil {
res.Properties = properties.NewFromHashmap(o.GetProperties())
}
return res
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment