From c90e7d4993d7c6d591d921cf8ef685745bcce968 Mon Sep 17 00:00:00 2001 From: Oleksandr Garagatyi Date: Wed, 24 Apr 2019 16:18:51 +0300 Subject: [PATCH] Naming convention (#49) Make broker download metas using new naming convention Details at https://github.com/eclipse/che-plugin-registry/issues/55 Signed-off-by: Oleksandr Garagatyi --- Makefile | 3 +- brokers/che-plugin-broker/broker.go | 14 +- brokers/che-plugin-broker/broker_test.go | 2 + brokers/theia/broker.go | 14 +- brokers/theia/broker_test.go | 44 ++--- brokers/unified/broker.go | 38 +++-- brokers/unified/broker_test.go | 104 +++++++++--- brokers/unified/cmd/main.go | 16 +- brokers/vscode/broker.go | 46 +++--- brokers/vscode/broker_test.go | 194 ++++++++++++++--------- cfg/cfg.go | 31 +--- common/events.go | 2 +- model/model.go | 15 +- storage/storage.go | 2 + 14 files changed, 304 insertions(+), 221 deletions(-) diff --git a/Makefile b/Makefile index 48138a18..8b1196c3 100644 --- a/Makefile +++ b/Makefile @@ -44,8 +44,7 @@ test-local: --disable-push \ --runtime-id wsId:env:ownerId \ --registry-address https://che-plugin-registry.openshift.io \ - --metas ./config-plugin-ids.json \ - --download-metas + --metas ./config-plugin-ids.json .PHONY: test-local-legacy test-local-legacy: diff --git a/brokers/che-plugin-broker/broker.go b/brokers/che-plugin-broker/broker.go index 80f9049a..46bf73c5 100644 --- a/brokers/che-plugin-broker/broker.go +++ b/brokers/che-plugin-broker/broker.go @@ -118,7 +118,7 @@ func (cheBroker *chePluginBrokerImpl) PushEvents(tun *jsonrpc.Tunnel) { } func (cheBroker *chePluginBrokerImpl) ProcessPlugin(meta model.PluginMeta) error { - cheBroker.PrintDebug("Stared processing plugin '%s:%s'", meta.ID, meta.Version) + cheBroker.PrintDebug("Stared processing plugin '%s'", meta.ID) url := meta.URL switch getTypeOfURL(url) { @@ -139,13 +139,13 @@ func (cheBroker *chePluginBrokerImpl) processYAML(meta *model.PluginMeta, url st } chePluginYamlPath := filepath.Join(workDir, pluginFileName) - cheBroker.PrintDebug("Downloading plugin definition '%s' for plugin '%s:%s' to '%s'", url, meta.ID, meta.Version, chePluginYamlPath) + cheBroker.PrintDebug("Downloading plugin definition '%s' for plugin '%s' to '%s'", url, meta.ID, chePluginYamlPath) err = cheBroker.ioUtil.Download(url, chePluginYamlPath) if err != nil { return err } - cheBroker.PrintDebug("Resolving '%s:%s'", meta.ID, meta.Version) + cheBroker.PrintDebug("Resolving '%s'", meta.ID) err = cheBroker.resolveToolingConfig(meta, workDir) if err != nil { return err @@ -162,20 +162,20 @@ func (cheBroker *chePluginBrokerImpl) processArchive(meta *model.PluginMeta, url pluginPath := filepath.Join(workDir, "plugin") // Download an archive - cheBroker.PrintDebug("Downloading archive '%s' for plugin '%s:%s' to '%s'", url, meta.ID, meta.Version, archivePath) + cheBroker.PrintDebug("Downloading archive '%s' for plugin '%s' to '%s'", url, meta.ID, archivePath) err = cheBroker.ioUtil.Download(url, archivePath) if err != nil { return err } // Untar it - cheBroker.PrintDebug("Untarring archive '%s' for plugin '%s:%s' to '%s'", url, meta.ID, meta.Version, archivePath) + cheBroker.PrintDebug("Unpacking archive '%s' for plugin '%s' to '%s'", url, meta.ID, archivePath) err = cheBroker.ioUtil.Untar(archivePath, pluginPath) if err != nil { return err } - cheBroker.PrintDebug("Resolving '%s:%s'", meta.ID, meta.Version) + cheBroker.PrintDebug("Resolving '%s'", meta.ID) err = cheBroker.resolveToolingConfig(meta, pluginPath) if err != nil { return err @@ -185,7 +185,7 @@ func (cheBroker *chePluginBrokerImpl) processArchive(meta *model.PluginMeta, url return nil } - cheBroker.PrintDebug("Copying dependencies for '%s:%s'", meta.ID, meta.Version) + cheBroker.PrintDebug("Copying dependencies for '%s'", meta.ID) return cheBroker.copyDependencies(pluginPath) } diff --git a/brokers/che-plugin-broker/broker_test.go b/brokers/che-plugin-broker/broker_test.go index 40decbbe..f14ae68a 100644 --- a/brokers/che-plugin-broker/broker_test.go +++ b/brokers/che-plugin-broker/broker_test.go @@ -221,6 +221,7 @@ func TestProcessPlugin(t *testing.T) { { ID: meta.ID, Version: meta.Version, + Name: meta.Name, Endpoints: toolingConf.Endpoints, Containers: toolingConf.Containers, Editors: toolingConf.Editors, @@ -321,6 +322,7 @@ func TestProcessPluginWithYaml(t *testing.T) { { ID: meta.ID, Version: meta.Version, + Name: meta.Name, Endpoints: toolingConf.Endpoints, Containers: toolingConf.Containers, Editors: toolingConf.Editors, diff --git a/brokers/theia/broker.go b/brokers/theia/broker.go index 5dd4603c..15068ea2 100644 --- a/brokers/theia/broker.go +++ b/brokers/theia/broker.go @@ -104,7 +104,7 @@ func (b *brokerImpl) PushEvents(tun *jsonrpc.Tunnel) { } func (b *brokerImpl) ProcessPlugin(meta model.PluginMeta) error { - b.PrintDebug("Stared processing plugin '%s:%s'", meta.ID, meta.Version) + b.PrintDebug("Started processing plugin '%s'", meta.ID) url := meta.URL workDir, err := b.ioUtil.TempDir("", "theia-plugin-broker") @@ -116,14 +116,14 @@ func (b *brokerImpl) ProcessPlugin(meta model.PluginMeta) error { unpackedPath := filepath.Join(workDir, "plugin") // Download an archive - b.PrintDebug("Downloading archive '%s' for plugin '%s:%s' to '%s'", url, meta.ID, meta.Version, archivePath) + b.PrintDebug("Downloading archive '%s' for plugin '%s' to '%s'", url, meta.ID, archivePath) err = b.ioUtil.Download(url, archivePath) if err != nil { return err } // Unzip it - b.PrintDebug("Unzipping archive '%s' for plugin '%s:%s' to '%s'", url, meta.ID, meta.Version, unpackedPath) + b.PrintDebug("Unzipping archive '%s' for plugin '%s' to '%s'", url, meta.ID, unpackedPath) err = b.ioUtil.Unzip(archivePath, unpackedPath) if err != nil { return err @@ -171,8 +171,8 @@ func (b *brokerImpl) getPluginImage(pj *PackageJSON) (string, error) { } func (b *brokerImpl) injectTheiaFile(meta model.PluginMeta, archivePath string) error { - b.PrintDebug("Copying Theia plugin '%s:%s'", meta.ID, meta.Version) - pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.theia", meta.ID, meta.Version)) + b.PrintDebug("Copying Theia plugin '%s'", meta.ID) + pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s.theia", meta.Publisher, meta.Name, meta.Version)) err := b.ioUtil.CopyFile(archivePath, pluginPath) if err != nil { return err @@ -182,8 +182,8 @@ func (b *brokerImpl) injectTheiaFile(meta model.PluginMeta, archivePath string) func (b *brokerImpl) injectTheiaRemotePlugin(meta model.PluginMeta, archiveFolder string, image string, pj *PackageJSON) error { if !cfg.OnlyApplyMetadataActions { - pluginFolderPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s", meta.ID, meta.Version)) - b.PrintDebug("Copying Theia remote plugin '%s:%s' from '%s' to '%s'", meta.ID, meta.Version, archiveFolder, pluginFolderPath) + pluginFolderPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s", meta.Publisher, meta.Name, meta.Version)) + b.PrintDebug("Copying Theia remote plugin '%s' from '%s' to '%s'", meta.ID, archiveFolder, pluginFolderPath) err := b.ioUtil.CopyResource(archiveFolder, pluginFolderPath) if err != nil { return err diff --git a/brokers/theia/broker_test.go b/brokers/theia/broker_test.go index 45481152..f77da58f 100644 --- a/brokers/theia/broker_test.go +++ b/brokers/theia/broker_test.go @@ -37,7 +37,7 @@ var ( Broker: bMock, ioUtil: uMock, storage: storage.New(), - rand: randMock, + rand: randMock, } ) @@ -46,7 +46,7 @@ func TestProcessRemotePlugin(t *testing.T) { Broker: bMock, ioUtil: uMock, storage: storage.New(), - rand: randMock, + rand: randMock, } workDir := tests.CreateTestWorkDir() defer tests.RemoveAll(workDir) @@ -54,11 +54,13 @@ func TestProcessRemotePlugin(t *testing.T) { unarchivedPath := filepath.Join(workDir, "plugin") packageJSONPath := filepath.Join(unarchivedPath, "package.json") meta := model.PluginMeta{ - ID: "test-id", - Version: "test-v", - URL: "http://test.url", + ID: "test-id", + Name: "test-name", + Publisher: "test-publisher", + Version: "test-v", + URL: "http://test.url", } - pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s", meta.ID, meta.Version)) + pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s", meta.Publisher, meta.Name, meta.Version)) packageJSON := PackageJSON{ PackageJSON: model.PackageJSON{ Name: "test-name", @@ -101,8 +103,10 @@ func expectedPlugins(meta model.PluginMeta, image string, publisher string, pubN prettyID := re.ReplaceAllString(publisher+"_"+pubName, `_`) expectedPlugins := []model.ChePlugin{ { - ID: meta.ID, - Version: meta.Version, + ID: meta.ID, + Version: meta.Version, + Name: meta.Name, + Publisher: meta.Publisher, Endpoints: []model.Endpoint{ { Name: "randomEndpointName", @@ -153,7 +157,7 @@ func TestProcessRegularPlugin(t *testing.T) { Broker: bMock, ioUtil: uMock, storage: storage.New(), - rand: randMock, + rand: randMock, } workDir := tests.CreateTestWorkDir() defer tests.RemoveAll(workDir) @@ -165,7 +169,7 @@ func TestProcessRegularPlugin(t *testing.T) { Version: "test-v", URL: "http://test.url", } - pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.theia", meta.ID, meta.Version)) + pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s.theia", meta.Publisher, meta.Name, meta.Version)) packageJSON := PackageJSON{ PackageJSON: model.PackageJSON{ Name: "test-name", @@ -320,11 +324,13 @@ func TestProcessPluginErrorIfArchiveCopyingFails(t *testing.T) { unarchivedPath := filepath.Join(workDir, "plugin") packageJSONPath := filepath.Join(unarchivedPath, "package.json") meta := model.PluginMeta{ - ID: "test-id", - Version: "test-v", - URL: "http://test.url", + ID: "test-id", + Version: "test-v", + Name: "test-name", + Publisher: "test-publisher", + URL: "http://test.url", } - pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.theia", meta.ID, meta.Version)) + pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s.theia", meta.Publisher, meta.Name, meta.Version)) packageJSON := PackageJSON{ PackageJSON: model.PackageJSON{ Name: "test-name", @@ -359,11 +365,13 @@ func TestProcessPluginErrorIfArchiveFolderCopyingFails(t *testing.T) { unarchivedPath := filepath.Join(workDir, "plugin") packageJSONPath := filepath.Join(unarchivedPath, "package.json") meta := model.PluginMeta{ - ID: "test-id", - Version: "test-v", - URL: "http://test.url", + ID: "test-id", + Version: "test-v", + Name: "test-name", + Publisher: "test-publisher", + URL: "http://test.url", } - pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s", meta.ID, meta.Version)) + pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s", meta.Publisher, meta.Name, meta.Version)) packageJSON := PackageJSON{ PackageJSON: model.PackageJSON{ Name: "test-name", diff --git a/brokers/unified/broker.go b/brokers/unified/broker.go index bd776a47..e281b579 100644 --- a/brokers/unified/broker.go +++ b/brokers/unified/broker.go @@ -37,7 +37,7 @@ const VscodePluginType = "vs code extension" // RegistryURLFormat specifies the format string for registry urls // when downloading metas -const RegistryURLFormat = "%s/%s/%s/meta.yaml" +const RegistryURLFormat = "%s/%s/meta.yaml" // Broker is used to process Che plugins type Broker struct { @@ -73,23 +73,18 @@ func NewBroker() *Broker { } // DownloadMetasAndStart downloads metas from plugin registry for specified -// pluginFQNs and then calls Start for those metas -func (b *Broker) DownloadMetasAndStart(pluginFQNs []model.PluginFQN, defaultRegistry string) { +// pluginFQNs and then executes plugins metas processing and sending data to Che master +func (b *Broker) Start(pluginFQNs []model.PluginFQN, defaultRegistry string) { pluginMetas, err := b.getPluginMetas(pluginFQNs, defaultRegistry) if err != nil { b.PrintFatal("Failed to download plugin metas: %s", err) } - b.Start(pluginMetas) -} - -// Start executes plugins metas processing and sending data to Che master -func (b *Broker) Start(metas []model.PluginMeta) { defer b.CloseConsumers() b.PubStarted() b.PrintInfo("Unified Che Plugin Broker") - b.PrintPlan(metas) + b.PrintPlan(pluginMetas) - err := b.ProcessPlugins(metas) + err = b.ProcessPlugins(pluginMetas) if err != nil { b.PubFailed(err.Error()) b.PrintFatal(err.Error()) @@ -150,30 +145,33 @@ func (b *Broker) ProcessPlugins(metas []model.PluginMeta) error { func (b *Broker) getPluginMetas(plugins []model.PluginFQN, defaultRegistry string) ([]model.PluginMeta, error) { metas := make([]model.PluginMeta, 0, len(plugins)) for _, plugin := range plugins { - log.Printf("Fetching plugin meta.yaml for %s:%s", plugin.ID, plugin.Version) + log.Printf("Fetching plugin meta.yaml for %s", plugin.ID) registry, err := getRegistryURL(plugin, defaultRegistry) if err != nil { return nil, err } - pluginURL := fmt.Sprintf(RegistryURLFormat, registry, plugin.ID, plugin.Version) + pluginURL := fmt.Sprintf(RegistryURLFormat, registry, plugin.ID) pluginRaw, err := b.utils.Fetch(pluginURL) if err != nil { if httpErr, ok := err.(*utils.HTTPError); ok { return nil, fmt.Errorf( - "failed to fetch plugin meta.yaml for plugin '%s:%s' from registry '%s': %s. Response body: %s", - plugin.ID, plugin.Version, registry, httpErr, httpErr.Body) + "failed to fetch plugin meta.yaml for plugin '%s' from registry '%s': %s. Response body: %s", + plugin.ID, registry, httpErr, httpErr.Body) } else { return nil, fmt.Errorf( - "failed to fetch plugin meta.yaml for plugin '%s:%s' from registry '%s': %s", - plugin.ID, plugin.Version, registry, err) + "failed to fetch plugin meta.yaml for plugin '%s' from registry '%s': %s", + plugin.ID, registry, err) } } var pluginMeta model.PluginMeta if err := yaml.Unmarshal(pluginRaw, &pluginMeta); err != nil { return nil, fmt.Errorf( - "failed to unmarshal downloaded meta.yaml for plugin '%s:%s': %s", - plugin.ID, plugin.Version, err) + "failed to unmarshal downloaded meta.yaml for plugin '%s': %s", plugin.ID, err) + } + // Ensure ID field is set since it is used all over the place in broker + if pluginMeta.ID == "" { + pluginMeta.ID = plugin.ID } metas = append(metas, pluginMeta) } @@ -208,9 +206,9 @@ func sortMetas(metas []model.PluginMeta) (che []model.PluginMeta, theia []model. case TheiaPluginType: theiaMetas = append(theiaMetas, meta) case "": - return nil, nil, nil, fmt.Errorf("Type field is missing in meta information of plugin '%s:%s'", meta.ID, meta.Version) + return nil, nil, nil, fmt.Errorf("Type field is missing in meta information of plugin '%s'", meta.ID) default: - return nil, nil, nil, fmt.Errorf("Type '%s' of plugin '%s:%s' is unsupported", meta.Type, meta.ID, meta.Version) + return nil, nil, nil, fmt.Errorf("Type '%s' of plugin '%s' is unsupported", meta.Type, meta.ID) } } diff --git a/brokers/unified/broker_test.go b/brokers/unified/broker_test.go index 83ef33c0..7d5b8604 100644 --- a/brokers/unified/broker_test.go +++ b/brokers/unified/broker_test.go @@ -256,11 +256,13 @@ func TestBroker_processPlugins(t *testing.T) { Type: "Unsupported type", ID: "test id", Version: "test version", + Publisher: "test publisher", + Name: "test name", }, }, }, want: want{ - err: "Type 'Unsupported type' of plugin 'test id:test version' is unsupported", + err: "Type 'Unsupported type' of plugin 'test id' is unsupported", }, }, { @@ -271,11 +273,13 @@ func TestBroker_processPlugins(t *testing.T) { Type: "", ID: "test id", Version: "test version", + Publisher: "test publisher", + Name: "test name", }, }, }, want: want{ - err: "Type field is missing in meta information of plugin 'test id:test version'", + err: "Type field is missing in meta information of plugin 'test id'", }, }, } @@ -314,8 +318,8 @@ func TestBroker_processPlugins(t *testing.T) { } func TestBroker_getPluginMetas(t *testing.T) { - const defaultRegistry = "defaultRegistry" - const RegistryURLFormat = "%s/%s/%s/meta.yaml" + const defaultRegistry = "http://defaultRegistry.com" + const RegistryURLFormat = "%s/%s/meta.yaml" type args struct { fqns []model.PluginFQN @@ -366,8 +370,7 @@ func TestBroker_getPluginMetas(t *testing.T) { fetchURL: fmt.Sprintf( RegistryURLFormat, defaultRegistry+"/plugins", - pluginFQNWithoutRegistry.ID, - pluginFQNWithoutRegistry.Version), + pluginFQNWithoutRegistry.ID), }, mocks: successMock, }, @@ -382,8 +385,7 @@ func TestBroker_getPluginMetas(t *testing.T) { fetchURL: fmt.Sprintf( RegistryURLFormat, pluginFQNWithRegistry.Registry, - pluginFQNWithRegistry.ID, - pluginFQNWithRegistry.Version), + pluginFQNWithRegistry.ID), }, mocks: successMock, }, @@ -398,8 +400,7 @@ func TestBroker_getPluginMetas(t *testing.T) { fetchURL: fmt.Sprintf( RegistryURLFormat, pluginFQNWithRegistry.Registry, - pluginFQNWithRegistry.ID, - pluginFQNWithRegistry.Version), + pluginFQNWithRegistry.ID), }, mocks: successMock, }, @@ -426,8 +427,7 @@ func TestBroker_getPluginMetas(t *testing.T) { fetchURL: fmt.Sprintf( RegistryURLFormat, strings.TrimSuffix(pluginFQNWithRegistryTrailingSlash.Registry, "/"), - pluginFQNWithRegistryTrailingSlash.ID, - pluginFQNWithRegistryTrailingSlash.Version), + pluginFQNWithRegistryTrailingSlash.ID), }, mocks: successMock, }, @@ -442,8 +442,75 @@ func TestBroker_getPluginMetas(t *testing.T) { fetchURL: fmt.Sprintf( RegistryURLFormat, defaultRegistry+"/plugins", - pluginFQNWithoutRegistry.ID, - pluginFQNWithoutRegistry.Version), + pluginFQNWithoutRegistry.ID), + }, + mocks: successMock, + }, + { + name: "Supports default registry address with path with trailing slash", + args: args{ + fqns: []model.PluginFQN{pluginFQNWithoutRegistry}, + defaultRegistry: defaultRegistry + "/v2/", + }, + want: want{ + errRegexp: nil, + fetchURL: fmt.Sprintf( + RegistryURLFormat, + defaultRegistry+"/v2/plugins", + pluginFQNWithoutRegistry.ID), + }, + mocks: successMock, + }, + { + name: "Supports default registry address with path with no trailing slash", + args: args{ + fqns: []model.PluginFQN{pluginFQNWithoutRegistry}, + defaultRegistry: defaultRegistry + "/v2", + }, + want: want{ + errRegexp: nil, + fetchURL: fmt.Sprintf( + RegistryURLFormat, + defaultRegistry+"/v2/plugins", + pluginFQNWithoutRegistry.ID), + }, + mocks: successMock, + }, + { + name: "Supports custom registry address with path with trailing slash", + args: args{ + fqns: []model.PluginFQN{ + { + ID: "test-with-registry/2.0", + Registry: "http://test-registry.com/v3/", + }}, + defaultRegistry: defaultRegistry, + }, + want: want{ + errRegexp: nil, + fetchURL: fmt.Sprintf( + RegistryURLFormat, + "http://test-registry.com/v3", + "test-with-registry/2.0"), + }, + mocks: successMock, + }, + { + name: "Supports custom registry address with path with no trailing slash", + args: args{ + fqns: []model.PluginFQN{ + { + ID: "test-with-registry/2.0", + Registry: "http://test-registry.com/v4", + }}, + defaultRegistry: defaultRegistry, + }, + want: want{ + errRegexp: nil, + fetchURL: fmt.Sprintf( + RegistryURLFormat, + "http://test-registry.com/v4", + "test-with-registry/2.0"), }, mocks: successMock, }, @@ -506,19 +573,16 @@ func createCheEditorMeta(ID string) model.PluginMeta { } var pluginFQNWithoutRegistry = model.PluginFQN{ - ID: "test-no-registry", - Version: "1.0", + ID: "test-no-registry/1.0", } var pluginFQNWithRegistry = model.PluginFQN{ - ID: "test-with-registry", - Version: "2.0", + ID: "test-with-registry/2.0", Registry: "test-registry", } var pluginFQNWithRegistryTrailingSlash = model.PluginFQN{ - ID: "test-with-registry-suffix", - Version: "3.0", + ID: "test-with-registry-suffix/3.0", Registry: "test-registry/", } diff --git a/brokers/unified/cmd/main.go b/brokers/unified/cmd/main.go index 514a8e37..cbfb66e8 100644 --- a/brokers/unified/cmd/main.go +++ b/brokers/unified/cmd/main.go @@ -34,17 +34,9 @@ func main() { broker.PushEvents(statusTun) } - if cfg.DownloadMetas { - pluginFQNs, err := cfg.ParsePluginFQNs() - if err != nil { - broker.PrintFatal("Failed to process plugin fully qualified names from config: %s", err) - } - broker.DownloadMetasAndStart(pluginFQNs, cfg.RegistryAddress) - } else { - pluginMetas, err := cfg.ReadConfig() - if err != nil { - broker.PrintFatal("Failed to process plugin fully qualified names from config: %s", err) - } - broker.Start(pluginMetas) + pluginFQNs, err := cfg.ParsePluginFQNs() + if err != nil { + broker.PrintFatal("Failed to process plugin fully qualified names from config: %s", err) } + broker.Start(pluginFQNs, cfg.RegistryAddress) } diff --git a/brokers/vscode/broker.go b/brokers/vscode/broker.go index 3e20f61f..8d559af5 100644 --- a/brokers/vscode/broker.go +++ b/brokers/vscode/broker.go @@ -36,8 +36,8 @@ import ( const marketplace = "https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery" const bodyFmt = `{"filters":[{"criteria":[{"filterType":7,"value":"%s"}],"pageNumber":1,"pageSize":1,"sortBy":0, "sortOrder":0 }],"assetTypes":["Microsoft.VisualStudio.Services.VSIXPackage"],"flags":131}` const assetType = "Microsoft.VisualStudio.Services.VSIXPackage" -const errorMutuallyExclusiveExtFieldsTemplate = "VS Code extension description of the plugin '%s:%s' contains more than one mutually exclusive field 'attributes.extension', 'url', 'extensions'" -const errorNoExtFieldsTemplate = "Neither 'extension' nor 'url' nor 'extensions' field found in VS Code extension description of the plugin '%s:%s'" +const errorMutuallyExclusiveExtFieldsTemplate = "VS Code extension description of the plugin '%s' contains more than one mutually exclusive field 'attributes.extension', 'url', 'extensions'" +const errorNoExtFieldsTemplate = "Neither 'extension' nor 'url' nor 'extensions' field found in VS Code extension description of the plugin '%s'" type brokerImpl struct { common.Broker @@ -109,7 +109,7 @@ func (b *brokerImpl) PushEvents(tun *jsonrpc.Tunnel) { } func (b *brokerImpl) ProcessPlugin(meta model.PluginMeta) error { - b.PrintDebug("Stared processing plugin '%s:%s'", meta.ID, meta.Version) + b.PrintDebug("Started processing plugin '%s'", meta.ID) URLs, err := b.getBinariesURLs(meta) if err != nil { @@ -142,11 +142,11 @@ func (b *brokerImpl) ProcessPlugin(meta model.PluginMeta) error { } func (b *brokerImpl) injectLocalPlugin(meta model.PluginMeta, archivesPaths []string) error { - b.PrintDebug("Copying VS Code plugin '%s:%s'", meta.ID, meta.Version) + b.PrintDebug("Copying VS Code plugin '%s'", meta.ID) for _, path := range archivesPaths { pluginName := b.generatePluginArchiveName(meta) pluginPath := filepath.Join("/plugins", pluginName) - b.PrintDebug("Copying VS Code extension archive from '%s' to '%s' for plugin '%s:%s'", path, pluginPath, meta.ID, meta.Version) + b.PrintDebug("Copying VS Code extension archive from '%s' to '%s' for plugin '%s'", path, pluginPath, meta.ID) err := b.ioUtil.CopyFile(path, pluginPath) if err != nil { return err @@ -160,7 +160,7 @@ func (b *brokerImpl) injectRemotePlugin(meta model.PluginMeta, image string, arc for _, archive := range archivesPaths { // Unzip it unpackedPath := filepath.Join(workDir, "extension", b.rand.String(10)) - b.PrintDebug("Unzipping archive '%s' for plugin '%s:%s' to '%s'", archive, meta.ID, meta.Version, unpackedPath) + b.PrintDebug("Unzipping archive '%s' for plugin '%s' to '%s'", archive, meta.ID, unpackedPath) err := b.ioUtil.Unzip(archive, unpackedPath) if err != nil { return err @@ -175,7 +175,7 @@ func (b *brokerImpl) injectRemotePlugin(meta model.PluginMeta, image string, arc pluginName := b.generatePluginFolderName(meta, *pj) pluginFolderPath := filepath.Join("/plugins", pluginName) - b.PrintDebug("Copying VS Code extension '%s:%s' from '%s' to '%s'", meta.ID, meta.Version, unpackedPath, pluginFolderPath) + b.PrintDebug("Copying VS Code extension '%s' from '%s' to '%s'", meta.ID, unpackedPath, pluginFolderPath) err = b.ioUtil.CopyResource(unpackedPath, pluginFolderPath) if err != nil { return err @@ -191,8 +191,8 @@ func (b *brokerImpl) downloadArchives(URLs []string, meta model.PluginMeta, work paths := make([]string, 0) for _, URL := range URLs { archivePath := filepath.Join(workDir, "pluginArchive"+b.rand.String(10)) - b.PrintDebug("Downloading VS Code extension archive '%s' for plugin '%s:%s' to '%s'", URL, meta.ID, meta.Version, archivePath) - b.PrintInfo("Downloading VS Code extension for plugin '%s:%s'", meta.ID, meta.Version) + b.PrintDebug("Downloading VS Code extension archive '%s' for plugin '%s' to '%s'", URL, meta.ID, archivePath) + b.PrintInfo("Downloading VS Code extension for plugin '%s'", meta.ID) err := b.downloadArchive(URL, archivePath) paths = append(paths, archivePath) if err != nil { @@ -213,14 +213,14 @@ func (b *brokerImpl) getExtensionsAndURLs(meta model.PluginMeta) (e []string, u } if meta.Attributes != nil && meta.Attributes["extension"] != "" { if isSet { - return nil, nil, fmt.Errorf(errorMutuallyExclusiveExtFieldsTemplate, meta.ID, meta.Version) + return nil, nil, fmt.Errorf(errorMutuallyExclusiveExtFieldsTemplate, meta.ID) } isSet = true extensions = append(extensions, meta.Attributes["extension"]) } if meta.Extensions != nil && len(meta.Extensions) != 0 { if isSet { - return nil, nil, fmt.Errorf(errorMutuallyExclusiveExtFieldsTemplate, meta.ID, meta.Version) + return nil, nil, fmt.Errorf(errorMutuallyExclusiveExtFieldsTemplate, meta.ID) } isSet = true for _, v := range meta.Extensions { @@ -234,7 +234,7 @@ func (b *brokerImpl) getExtensionsAndURLs(meta model.PluginMeta) (e []string, u } } if !isSet { - return nil, nil, fmt.Errorf(errorNoExtFieldsTemplate, meta.ID, meta.Version) + return nil, nil, fmt.Errorf(errorNoExtFieldsTemplate, meta.ID) } return extensions, URLs, nil } @@ -265,11 +265,11 @@ func extensionOrURL(extensionOrURL string) (extension string, URL string) { func (b *brokerImpl) generatePluginFolderName(meta model.PluginMeta, pj model.PackageJSON) string { var re = regexp.MustCompile(`[^a-zA-Z_0-9]+`) prettyID := re.ReplaceAllString(pj.Publisher+"_"+pj.Name, "") - return fmt.Sprintf("%s.%s.%s", meta.ID, meta.Version, prettyID) + return fmt.Sprintf("%s.%s.%s.%s", meta.Publisher, meta.Name, meta.Version, prettyID) } func (b *brokerImpl) generatePluginArchiveName(meta model.PluginMeta) string { - return fmt.Sprintf("%s.%s.%s.vsix", meta.ID, meta.Version, b.rand.String(10)) + return fmt.Sprintf("%s.%s.%s.%s.vsix", meta.Publisher, meta.Name, meta.Version, b.rand.String(10)) } func (b *brokerImpl) getExtensionArchiveURL(extension string, meta model.PluginMeta) (string, error) { @@ -316,29 +316,29 @@ func (b *brokerImpl) fetchExtensionInfo(extension string, meta model.PluginMeta) re := regexp.MustCompile(`^vscode:extension/(.*)`) groups := re.FindStringSubmatch(extension) if len(groups) != 2 { - return nil, fmt.Errorf("Parsing of VS Code extension ID '%s' failed for plugin '%s:%s'. Extension should start from 'vscode:extension/'", extension, meta.ID, meta.Version) + return nil, fmt.Errorf("Parsing of VS Code extension ID '%s' failed for plugin '%s'. Extension should start from 'vscode:extension/'", extension, meta.ID) } extName := groups[1] body := []byte(fmt.Sprintf(bodyFmt, extName)) req, err := http.NewRequest("POST", marketplace, bytes.NewBuffer(body)) if err != nil { - return nil, fmt.Errorf("VS Code extension id '%s' fetching failed for plugin %s:%s. Error: %s", extension, meta.ID, meta.Version, err) + return nil, fmt.Errorf("VS Code extension id '%s' fetching failed for plugin %s. Error: %s", extension, meta.ID, err) } req.Header.Set("Accept", "application/json;api-version=3.0-preview.1") req.Header.Set("Content-Type", "application/json") resp, err := b.client.Do(req) if err != nil { - return nil, fmt.Errorf("VS Code extension downloading failed %s:%s. Error: %s", meta.ID, meta.Version, err) + return nil, fmt.Errorf("VS Code extension downloading failed %s. Error: %s", meta.ID, err) } defer utils.Close(resp.Body) body, err = ioutil.ReadAll(resp.Body) if err != nil { - return nil, fmt.Errorf("VS Code extension downloading failed %s:%s. Error: %s", meta.ID, meta.Version, err) + return nil, fmt.Errorf("VS Code extension downloading failed %s. Error: %s", meta.ID, err) } if resp.StatusCode != 200 { - errMsg := "VS Code extension downloading failed %s:%s. Status: %v. Body: " + string(body) - return nil, fmt.Errorf(errMsg, meta.ID, meta.Version, resp.StatusCode) + errMsg := "VS Code extension downloading failed %s. Status: %v. Body: " + string(body) + return nil, fmt.Errorf(errMsg, meta.ID, resp.StatusCode) } return body, nil @@ -348,7 +348,7 @@ func findAssetURL(response []byte, meta model.PluginMeta) (string, error) { obj := &marketplaceResponse{} err := json.Unmarshal(response, obj) if err != nil { - return "", fmt.Errorf("Failed to parse VS Code extension marketplace response for plugin %s:%s", meta.ID, meta.Version) + return "", fmt.Errorf("Failed to parse VS Code extension marketplace response for plugin %s", meta.ID) } switch { case len(obj.Results) == 0, @@ -356,14 +356,14 @@ func findAssetURL(response []byte, meta model.PluginMeta) (string, error) { len(obj.Results[0].Extensions[0].Versions) == 0, len(obj.Results[0].Extensions[0].Versions[0].Files) == 0: - return "", fmt.Errorf("Failed to parse VS Code extension marketplace response for plugin %s:%s", meta.ID, meta.Version) + return "", fmt.Errorf("Failed to parse VS Code extension marketplace response for plugin %s", meta.ID) } for _, f := range obj.Results[0].Extensions[0].Versions[0].Files { if f.AssetType == assetType { return f.Source, nil } } - return "", fmt.Errorf("VS Code extension archive information is not found in marketplace response for plugin %s:%s", meta.ID, meta.Version) + return "", fmt.Errorf("VS Code extension archive information is not found in marketplace response for plugin %s", meta.ID) } func (b *brokerImpl) getPackageJSON(pluginFolder string) (*model.PackageJSON, error) { diff --git a/brokers/vscode/broker_test.go b/brokers/vscode/broker_test.go index 076353c5..14f206db 100644 --- a/brokers/vscode/broker_test.go +++ b/brokers/vscode/broker_test.go @@ -34,13 +34,15 @@ import ( ) const ( - extName = "Test-name" - extPublisher = "Test-publisher" - vsixURL = "http://test.url" - vsixBrokenURL = "http://broken.test.url" - pluginID = "tid" - pluginVersion = "tv" - image = "test/test:tag" + extName = "Test-name" + extPublisher = "Test-publisher" + vsixURL = "http://test.url" + vsixBrokenURL = "http://broken.test.url" + pluginID = "tid" + pluginVersion = "tv" + image = "test/test:tag" + pluginPublisher = "test publisher" + pluginName = "test name" ) type mocks struct { @@ -127,70 +129,84 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Return error when neither extension nor URL nor extensions are present", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Attributes: map[string]string{ "containerImage": image, }, }, - err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid"), }, { name: "Return error when neither attributes nor URL nor extensions are present", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, }, - err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid"), }, { name: "Return error when neither attributes nor URL are present and extensions are nil", meta: model.PluginMeta{ ID: pluginID, Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: nil, }, - err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid"), }, { name: "Return error when neither attributes nor URL are present and extensions are empty", meta: model.PluginMeta{ ID: pluginID, Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{}, }, - err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorNoExtFieldsTemplate, "tid"), }, { name: "Return error when both extension and URL fields are present", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, - URL: vsixURL, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, + URL: vsixURL, Attributes: map[string]string{ "extension": "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", "containerImage": image, }, }, - err: fmt.Sprintf(errorMutuallyExclusiveExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorMutuallyExclusiveExtFieldsTemplate, "tid"), }, { name: "Return error when both extensions and URL fields are present", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, - URL: vsixURL, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, + URL: vsixURL, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", }, }, - err: fmt.Sprintf(errorMutuallyExclusiveExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorMutuallyExclusiveExtFieldsTemplate, "tid"), }, { name: "Return error when both extensions and extension fields are present", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", }, @@ -198,13 +214,15 @@ func TestBroker_processPlugin(t *testing.T) { "extension": "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", }, }, - err: fmt.Sprintf(errorMutuallyExclusiveExtFieldsTemplate, "tid", "tv"), + err: fmt.Sprintf(errorMutuallyExclusiveExtFieldsTemplate, "tid"), }, { name: "Successful brokering of remote plugin with extension field", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Attributes: map[string]string{ "extension": "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", "containerImage": image, @@ -215,9 +233,11 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of remote plugin with URL field", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, - URL: vsixURL, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, + URL: vsixURL, Attributes: map[string]string{ "containerImage": image, }, @@ -227,8 +247,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of local plugin with extension field", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Attributes: map[string]string{ "extension": "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", }, @@ -238,9 +260,11 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of local plugin with URL field and empty attributes", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, - URL: vsixURL, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, + URL: vsixURL, Attributes: map[string]string{ }, }, @@ -249,17 +273,21 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of local plugin with URL field", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, - URL: vsixURL, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, + URL: vsixURL, }, want: expectedPluginsWithSingleLocalPlugin(), }, { name: "Successful brokering of local plugin with extensions field", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", }, @@ -269,8 +297,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of local plugin with extensions field and empty attributes", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Attributes: map[string]string{ }, Extensions: []string{ @@ -282,8 +312,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of local plugin with extensions field with several extensions", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", "vscode:extension/redhat-com.vscode-jdt-ls", @@ -295,8 +327,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of local plugin with extensions field with mixed extensions and archives URLs", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", "vscode:extension/redhat-com.vscode-jdt-ls", @@ -308,8 +342,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of remote plugin with extensions field with several extensions", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", "vscode:extension/redhat-com.vscode-jdt-ls", @@ -331,8 +367,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of remote plugin with extensions field with mixed extensions and archives URLs", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", vsixURL, @@ -354,8 +392,10 @@ func TestBroker_processPlugin(t *testing.T) { { name: "Successful brokering of remote plugin with extensions field", meta: model.PluginMeta{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Extensions: []string{ "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", }, @@ -411,8 +451,10 @@ func generateTheiaEnvVar(prettyID string) string { func expectedPluginsWithSingleRemotePluginWithSeveralExtensions(pluginTheiaEndpointVars ...string) []model.ChePlugin { expectedPlugin := model.ChePlugin{ - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Endpoints: []model.Endpoint{ { Name: "randomString1234567890", @@ -464,8 +506,10 @@ func expectedPluginsWithSingleRemotePlugin() []model.ChePlugin { prettyID := "Test_publisher_Test_name" expectedPlugins := []model.ChePlugin{ { - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, Endpoints: []model.Endpoint{ { Name: "randomString1234567890", @@ -514,8 +558,10 @@ func expectedPluginsWithSingleRemotePlugin() []model.ChePlugin { func expectedPluginsWithSingleLocalPlugin() []model.ChePlugin { expectedPlugins := []model.ChePlugin{ { - ID: pluginID, - Version: pluginVersion, + ID: pluginID, + Version: pluginVersion, + Publisher: pluginPublisher, + Name: pluginName, }, } return expectedPlugins @@ -528,7 +574,7 @@ func setUpSuccessfulCase(workDir string, meta model.PluginMeta, m *mocks, unzipF } m.u.On("Unzip", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Run(_unzipFunc).Return(nil) m.u.On("CopyResource", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(nil) - pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.randomString1234567890.vsix", meta.ID, meta.Version)) + pluginPath := filepath.Join("/plugins", fmt.Sprintf("%s.%s.%s.randomString1234567890.vsix", meta.Publisher, meta.Name, meta.Version)) m.u.On("CopyFile", mock.AnythingOfType("string"), pluginPath).Return(nil) m.cb.On("PrintDebug", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")) m.cb.On("PrintDebug", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")) @@ -590,7 +636,7 @@ func TestFetchExtensionInfo(t *testing.T) { roundTF test.RoundTripFunc }{ { - err: "Parsing of VS Code extension ID 'invalidExt' failed for plugin 'tid:tv'. Extension should start from 'vscode:extension/'", + err: "Parsing of VS Code extension ID 'invalidExt' failed for plugin 'tid'. Extension should start from 'vscode:extension/'", ext: "invalidExt", }, { @@ -631,7 +677,7 @@ func TestFetchExtensionInfo(t *testing.T) { }, { ext: "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", - err: "VS Code extension downloading failed tid:tv. Status: 400. Body: ", + err: "VS Code extension downloading failed tid. Status: 400. Body: ", roundTF: func(req *http.Request) *http.Response { return &http.Response{ StatusCode: 400, @@ -641,7 +687,7 @@ func TestFetchExtensionInfo(t *testing.T) { }, { ext: "vscode:extension/ms-kubernetes-tools.vscode-kubernetes-tools", - err: "VS Code extension downloading failed tid:tv. Status: 400. Body: " + "test error", + err: "VS Code extension downloading failed tid. Status: 400. Body: " + "test error", roundTF: func(req *http.Request) *http.Response { return &http.Response{ StatusCode: 400, @@ -689,23 +735,23 @@ func TestFindAssetURL(t *testing.T) { err string }{ { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte("{"), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte("{}"), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte(`{"results":[]}`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte(`{"results":null}`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte( `{ "results":[ @@ -725,7 +771,7 @@ func TestFindAssetURL(t *testing.T) { }`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte( `{ "results":[ @@ -744,7 +790,7 @@ func TestFindAssetURL(t *testing.T) { }`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte( `{ "results":[ @@ -760,7 +806,7 @@ func TestFindAssetURL(t *testing.T) { }`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte( `{ "results":[ @@ -775,7 +821,7 @@ func TestFindAssetURL(t *testing.T) { }`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte( `{ "results":[ @@ -787,7 +833,7 @@ func TestFindAssetURL(t *testing.T) { }`), }, { - err: "Failed to parse VS Code extension marketplace response for plugin tid:v", + err: "Failed to parse VS Code extension marketplace response for plugin tid", response: []byte( `{ "results":[ @@ -798,7 +844,7 @@ func TestFindAssetURL(t *testing.T) { }`), }, { - err: "VS Code extension archive information is not found in marketplace response for plugin tid:v", + err: "VS Code extension archive information is not found in marketplace response for plugin tid", response: []byte( `{ "results":[ diff --git a/cfg/cfg.go b/cfg/cfg.go index a07358b5..65cecbc3 100644 --- a/cfg/cfg.go +++ b/cfg/cfg.go @@ -62,11 +62,6 @@ var ( // RegistryAddress address of the plugin registry, if plugin IDs are specified in config instead of metas. // Used as a default registry if a plugin fully-qualified name does not specify a registry. RegistryAddress string - - // DownloadMetas specifies whether the broker should download plugin metas from the registry. If - // true, then config file should be a list of plugin fully-qualified names. Otherwise, the config - // file should contain the plugin metas to be processed. - DownloadMetas bool ) func init() { @@ -124,13 +119,7 @@ func init() { &RegistryAddress, "registry-address", "", - "Default address of registry from which to retrieve meta.yamls when plugin FQNs do not specify a registry. Ignored unless --download-metas is set", - ) - flag.BoolVar( - &DownloadMetas, - "download-metas", - false, - "Download plugin metadata from registry instead of process already-downloaded metas", + "Default address of registry from which to retrieve meta.yaml's when plugin FQNs do not specify a registry", ) } @@ -180,24 +169,6 @@ func Print() { log.Printf(" OwnerId: %s", RuntimeID.OwnerId) } -// ReadConfig reads content of file by path cfg.FilePath, -// parses its content as array of Che plugin meta objects and returns it. -// If any error occurs during read, log.Fatal is called. -// -// Deprecated -func ReadConfig() ([]model.PluginMeta, error) { - raw, err := readConfigFile() - if err != nil { - return nil, fmt.Errorf("failed to read config file: %s", err) - } - - metas := make([]model.PluginMeta, 0) - if err := json.Unmarshal(raw, &metas); err != nil { - return nil, fmt.Errorf("failed to unmarshal plugin metas: %s", err) - } - return metas, nil -} - // ParsePluginFQNs reads content of file at path cfg.Filepath and parses its // content as a list of fully-qualified Plugin names (id, version, registry). // If any error occurs, log.Fatal is called. diff --git a/common/events.go b/common/events.go index 451d16ea..3f2936ed 100644 --- a/common/events.go +++ b/common/events.go @@ -58,7 +58,7 @@ func (broker *brokerImpl) PrintPlan(metas []model.PluginMeta) { buffer.WriteString("List of plugins and editors to install\n") for _, plugin := range metas { - buffer.WriteString(fmt.Sprintf("- %s:%s - %s\n", plugin.ID, plugin.Version, plugin.Description)) + buffer.WriteString(fmt.Sprintf("- %s/%s/%s - %s\n", plugin.Publisher, plugin.Name, plugin.Version, plugin.Description)) } broker.PrintInfo(buffer.String()) diff --git a/model/model.go b/model/model.go index 5018d582..b4ebfa52 100644 --- a/model/model.go +++ b/model/model.go @@ -51,6 +51,10 @@ type PluginMeta struct { Name string `json:"name" yaml:"name"` + DisplayName string `json:"displayName" yaml:"displayName"` + + Publisher string `json:"publisher" yaml:"publisher"` + Type string `json:"type" yaml:"type"` Description string `json:"description" yaml:"description"` @@ -71,7 +75,6 @@ type PluginMeta struct { type PluginFQN struct { Registry string `json:"registry,omitempty" yaml:"registry,omitempty"` ID string `json:"id" yaml:"id"` - Version string `json:"version" yaml:"version"` } type Endpoint struct { @@ -125,12 +128,10 @@ type ToolingConf struct { } type ChePlugin struct { - ID string `json:"id" yaml:"id"` - Version string `json:"version" yaml:"version"` - //Name should not be propagated until Che Server requires it to have the following format "[a-z0-9]([-a-z0-9]*[a-z0-9])?" - //while it is not respected by all of plugin - //See https://github.com/eclipse/che/blob/251e5e261bac2bf4c93f113e52fd18d26b5989ab/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingValidator.java#L27 - //Name string `json:"name" yaml:"name"` + ID string `json:"id" yaml:"id"` + Version string `json:"version" yaml:"version"` + Name string `json:"name" yaml:"name"` + Publisher string `json:"publisher" yaml:"publisher"` Endpoints []Endpoint `json:"endpoints" yaml:"endpoints"` Containers []Container `json:"containers" yaml:"containers"` Editors []Editor `json:"editors" yaml:"editors"` diff --git a/storage/storage.go b/storage/storage.go index 787dab80..3370a3ba 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -69,6 +69,8 @@ func (s *Storage) AddPlugin(meta *model.PluginMeta, tooling *model.ToolingConf) defer s.Unlock() plugin := &model.ChePlugin{ ID: meta.ID, + Name: meta.Name, + Publisher: meta.Publisher, Version: meta.Version, Containers: tooling.Containers, Editors: tooling.Editors,