2018-05-22 19:43:36 +00:00
|
|
|
// Copyright 2016-2018, Pulumi Corporation.
|
|
|
|
//
|
|
|
|
// Licensed 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.
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
|
|
|
|
package workspace
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/tar"
|
|
|
|
"compress/gzip"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2018-02-06 15:20:04 +00:00
|
|
|
"os/exec"
|
2018-02-20 23:35:07 +00:00
|
|
|
"os/user"
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
2018-02-17 19:42:27 +00:00
|
|
|
"runtime"
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/blang/semver"
|
|
|
|
"github.com/djherbis/times"
|
|
|
|
"github.com/pkg/errors"
|
2018-02-06 15:20:04 +00:00
|
|
|
|
|
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
2018-05-15 22:28:00 +00:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/logging"
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
)
|
|
|
|
|
Look for language plugins next to `pulumi` when probing
When launching plugins today, `pulumi` looks in two places:
1. It looks to see if the plugin in on the $PATH and if so, uses
it. This makes it easy to force a specific version of a resource
provider to be used and is what happens at development time (since
resource providers make their way onto $PATH via GOBIN).
2. If the above fails, it looks in the "plugin cache" in
`~/.pulumi/plugins`. This is the location that `pulumi plugin
install` places plugins.
Unlike resource provider plugins, we don't yet deliver language
plugins via `pulumi plugin install` so the language provider plugins
must be on the `$PATH` to be found. This is okay, because when we ship
the SDK, we include the executables next to `pulumi` itself.
However, if a user chooses to not put `pulumi` on their $PATH, or they
do but it is a symlink to the real `pulumi` binary installed
somewhere, we'd fail to find the language plugins, since they would
not be on the `$PATH`
To address this, when probing for language plugins, also consider
binaries next to the currently running `pulumi` process.
Fixes #1956
2018-11-19 23:07:01 +00:00
|
|
|
const (
|
|
|
|
windowsGOOS = "windows"
|
|
|
|
)
|
|
|
|
|
2018-02-19 17:31:00 +00:00
|
|
|
// PluginInfo provides basic information about a plugin. Each plugin gets installed into a system-wide
|
|
|
|
// location, by default `~/.pulumi/plugins/<kind>-<name>-<version>/`. A plugin may contain multiple files,
|
|
|
|
// however the primary loadable executable must be named `pulumi-<kind>-<name>`.
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
type PluginInfo struct {
|
2018-02-06 17:57:32 +00:00
|
|
|
Name string // the simple name of the plugin.
|
2018-02-21 18:32:31 +00:00
|
|
|
Path string // the path that a plugin was loaded from.
|
2018-02-06 17:57:32 +00:00
|
|
|
Kind PluginKind // the kind of the plugin (language, resource, etc).
|
|
|
|
Version *semver.Version // the plugin's semantic version, if present.
|
|
|
|
Size int64 // the size of the plugin, in bytes.
|
|
|
|
InstallTime time.Time // the time the plugin was installed.
|
|
|
|
LastUsedTime time.Time // the last time the plugin was used.
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-19 17:31:00 +00:00
|
|
|
// Dir gets the expected plugin directory for this plugin.
|
|
|
|
func (info PluginInfo) Dir() string {
|
|
|
|
dir := fmt.Sprintf("%s-%s", info.Kind, info.Name)
|
|
|
|
if info.Version != nil {
|
|
|
|
dir = fmt.Sprintf("%s-v%s", dir, info.Version.String())
|
|
|
|
}
|
|
|
|
return dir
|
|
|
|
}
|
|
|
|
|
2018-02-17 19:42:27 +00:00
|
|
|
// File gets the expected filename for this plugin.
|
|
|
|
func (info PluginInfo) File() string {
|
|
|
|
return info.FilePrefix() + info.FileSuffix()
|
|
|
|
}
|
|
|
|
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
// FilePrefix gets the expected default file prefix for the plugin.
|
|
|
|
func (info PluginInfo) FilePrefix() string {
|
2018-02-19 17:31:00 +00:00
|
|
|
return fmt.Sprintf("pulumi-%s-%s", info.Kind, info.Name)
|
2018-02-06 15:20:04 +00:00
|
|
|
}
|
|
|
|
|
2018-02-17 19:42:27 +00:00
|
|
|
// FileSuffix returns the suffix for the plugin (if any).
|
|
|
|
func (info PluginInfo) FileSuffix() string {
|
Look for language plugins next to `pulumi` when probing
When launching plugins today, `pulumi` looks in two places:
1. It looks to see if the plugin in on the $PATH and if so, uses
it. This makes it easy to force a specific version of a resource
provider to be used and is what happens at development time (since
resource providers make their way onto $PATH via GOBIN).
2. If the above fails, it looks in the "plugin cache" in
`~/.pulumi/plugins`. This is the location that `pulumi plugin
install` places plugins.
Unlike resource provider plugins, we don't yet deliver language
plugins via `pulumi plugin install` so the language provider plugins
must be on the `$PATH` to be found. This is okay, because when we ship
the SDK, we include the executables next to `pulumi` itself.
However, if a user chooses to not put `pulumi` on their $PATH, or they
do but it is a symlink to the real `pulumi` binary installed
somewhere, we'd fail to find the language plugins, since they would
not be on the `$PATH`
To address this, when probing for language plugins, also consider
binaries next to the currently running `pulumi` process.
Fixes #1956
2018-11-19 23:07:01 +00:00
|
|
|
if runtime.GOOS == windowsGOOS {
|
2018-02-17 19:42:27 +00:00
|
|
|
return ".exe"
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2018-02-19 17:31:00 +00:00
|
|
|
// DirPath returns the directory where this plugin should be installed.
|
|
|
|
func (info PluginInfo) DirPath() (string, error) {
|
|
|
|
dir, err := GetPluginDir()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
2018-02-06 15:20:04 +00:00
|
|
|
}
|
2018-02-19 17:31:00 +00:00
|
|
|
return filepath.Join(dir, info.Dir()), nil
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-19 17:31:00 +00:00
|
|
|
// FilePath returns the full path where this plugin's primary executable should be installed.
|
|
|
|
func (info PluginInfo) FilePath() (string, error) {
|
|
|
|
dir, err := info.DirPath()
|
2018-02-17 19:42:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return filepath.Join(dir, info.File()), nil
|
|
|
|
}
|
|
|
|
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
// Delete removes the plugin from the cache. It also deletes any supporting files in the cache, which includes
|
|
|
|
// any files that contain the same prefix as the plugin itself.
|
|
|
|
func (info PluginInfo) Delete() error {
|
2018-02-19 17:31:00 +00:00
|
|
|
dir, err := info.DirPath()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return os.RemoveAll(dir)
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-19 18:58:03 +00:00
|
|
|
// SetFileMetadata adds extra metadata from the given file, representing this plugin's directory.
|
2018-04-09 19:51:32 +00:00
|
|
|
func (info *PluginInfo) SetFileMetadata(path string) error {
|
2018-02-19 18:58:03 +00:00
|
|
|
// Get the file info.
|
|
|
|
file, err := os.Stat(path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, get the size from the directory (or, if there is none, just the file).
|
2018-04-09 19:51:32 +00:00
|
|
|
size, err := getPluginSize(path)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "getting plugin dir %s size", path)
|
2018-02-19 18:58:03 +00:00
|
|
|
}
|
2018-04-09 19:51:32 +00:00
|
|
|
info.Size = size
|
2018-02-19 18:58:03 +00:00
|
|
|
|
|
|
|
// Next get the access times from the plugin binary itself.
|
|
|
|
tinfo := times.Get(file)
|
2018-02-22 17:26:19 +00:00
|
|
|
|
|
|
|
if tinfo.HasBirthTime() {
|
|
|
|
info.InstallTime = tinfo.BirthTime()
|
|
|
|
}
|
|
|
|
|
2018-02-19 18:58:03 +00:00
|
|
|
info.LastUsedTime = tinfo.AccessTime()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
// Install installs a plugin's tarball into the cache. It validates that plugin names are in the expected format.
|
|
|
|
func (info PluginInfo) Install(tarball io.ReadCloser) error {
|
2018-02-19 17:31:00 +00:00
|
|
|
// Fetch the directory into which we will expand this tarball, and create it.
|
2018-11-09 22:59:13 +00:00
|
|
|
finalDir, err := info.DirPath()
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-11-09 22:59:13 +00:00
|
|
|
|
2018-11-17 00:43:18 +00:00
|
|
|
// If part of the directory tree is missing, ioutil.TempDir will return an error, so make sure the path we're going
|
|
|
|
// to create the temporary folder in actually exists.
|
|
|
|
if err := os.MkdirAll(filepath.Dir(finalDir), 0700); err != nil {
|
|
|
|
return errors.Wrap(err, "creating plugin root")
|
|
|
|
}
|
|
|
|
|
2018-11-15 19:54:45 +00:00
|
|
|
tempDir, err := ioutil.TempDir(filepath.Dir(finalDir), fmt.Sprintf("%s.tmp", filepath.Base(finalDir)))
|
|
|
|
if err != nil {
|
2018-11-09 22:59:13 +00:00
|
|
|
return errors.Wrapf(err, "creating plugin directory %s", tempDir)
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
|
2018-11-15 19:54:45 +00:00
|
|
|
// If we early out of this function, try to remove the temp folder we created.
|
|
|
|
defer func() {
|
|
|
|
contract.IgnoreError(os.RemoveAll(tempDir))
|
|
|
|
}()
|
|
|
|
|
2018-11-17 01:53:57 +00:00
|
|
|
// Unzip and untar the file as we go. We do this inside a function so that the `defer`'s to close files happen
|
|
|
|
// before we later try to rename the directory. Otherwise, the open file handles cause issues on Windows.
|
|
|
|
err = (func() error {
|
|
|
|
defer contract.IgnoreClose(tarball)
|
|
|
|
gzr, err := gzip.NewReader(tarball)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "unzipping")
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
2018-11-17 01:53:57 +00:00
|
|
|
r := tar.NewReader(gzr)
|
|
|
|
for {
|
|
|
|
header, err := r.Next()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
} else if err != nil {
|
|
|
|
return errors.Wrapf(err, "untarring")
|
|
|
|
}
|
2018-02-19 17:31:00 +00:00
|
|
|
|
2018-11-17 01:53:57 +00:00
|
|
|
path := filepath.Join(tempDir, header.Name)
|
2018-02-19 17:31:00 +00:00
|
|
|
|
2018-11-17 01:53:57 +00:00
|
|
|
switch header.Typeflag {
|
|
|
|
case tar.TypeDir:
|
|
|
|
// Create any directories as needed.
|
|
|
|
if _, err := os.Stat(path); err != nil {
|
|
|
|
if err = os.MkdirAll(path, 0700); err != nil {
|
|
|
|
return errors.Wrapf(err, "untarring dir %s", path)
|
|
|
|
}
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
2018-11-17 01:53:57 +00:00
|
|
|
case tar.TypeReg:
|
|
|
|
// Expand files into the target directory.
|
|
|
|
dst, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "opening file %s for untar", path)
|
|
|
|
}
|
|
|
|
defer contract.IgnoreClose(dst)
|
|
|
|
if _, err = io.Copy(dst, r); err != nil {
|
|
|
|
return errors.Wrapf(err, "untarring file %s", path)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return errors.Errorf("unexpected plugin file type %s (%v)", header.Name, header.Typeflag)
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-17 01:53:57 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
})()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
2018-11-09 22:59:13 +00:00
|
|
|
|
2018-11-16 00:25:03 +00:00
|
|
|
// If two calls to `plugin install` for the same plugin are racing, the second one will be unable to rename
|
|
|
|
// the directory. That's OK, just ignore the error. The temp directory created as part of the install will be
|
|
|
|
// cleaned up when we exit by the defer above.
|
|
|
|
if err := os.Rename(tempDir, finalDir); err != nil && !os.IsExist(err) {
|
|
|
|
return errors.Wrap(err, "moving plugin")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (info PluginInfo) String() string {
|
2018-02-06 17:57:32 +00:00
|
|
|
var version string
|
|
|
|
if v := info.Version; v != nil {
|
|
|
|
version = fmt.Sprintf("-%s", v)
|
|
|
|
}
|
|
|
|
return info.Name + version
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PluginKind represents a kind of a plugin that may be dynamically loaded and used by Pulumi.
|
|
|
|
type PluginKind string
|
|
|
|
|
|
|
|
const (
|
|
|
|
// AnalyzerPlugin is a plugin that can be used as a resource analyzer.
|
|
|
|
AnalyzerPlugin PluginKind = "analyzer"
|
|
|
|
// LanguagePlugin is a plugin that can be used as a language host.
|
|
|
|
LanguagePlugin PluginKind = "language"
|
|
|
|
// ResourcePlugin is a plugin that can be used as a resource provider for custom CRUD operations.
|
|
|
|
ResourcePlugin PluginKind = "resource"
|
|
|
|
)
|
|
|
|
|
|
|
|
// IsPluginKind returns true if k is a valid plugin kind, and false otherwise.
|
|
|
|
func IsPluginKind(k string) bool {
|
|
|
|
switch PluginKind(k) {
|
|
|
|
case AnalyzerPlugin, LanguagePlugin, ResourcePlugin:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-17 19:42:27 +00:00
|
|
|
// HasPlugin returns true if the given plugin exists.
|
|
|
|
func HasPlugin(plug PluginInfo) bool {
|
2018-02-19 17:31:00 +00:00
|
|
|
dir, err := plug.DirPath()
|
2018-02-17 19:42:27 +00:00
|
|
|
if err == nil {
|
2018-02-19 17:31:00 +00:00
|
|
|
_, err := os.Stat(dir)
|
2018-02-17 19:42:27 +00:00
|
|
|
if err == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-04-05 23:37:50 +00:00
|
|
|
// HasPluginGTE returns true if the given plugin exists at the given version number or greater.
|
|
|
|
func HasPluginGTE(plug PluginInfo) (bool, error) {
|
|
|
|
// If an exact match, return true right away.
|
|
|
|
if HasPlugin(plug) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, load up the list of plugins and find one with the same name/type and >= version.
|
|
|
|
plugs, err := GetPlugins()
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
for _, p := range plugs {
|
|
|
|
if p.Name == plug.Name &&
|
|
|
|
p.Kind == plug.Kind &&
|
|
|
|
(p.Version != nil && plug.Version != nil && p.Version.GTE(*plug.Version)) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
// GetPluginDir returns the directory in which plugins on the current machine are managed.
|
|
|
|
func GetPluginDir() (string, error) {
|
2018-02-20 23:35:07 +00:00
|
|
|
u, err := user.Current()
|
|
|
|
if u == nil || err != nil {
|
|
|
|
return "", errors.Wrapf(err, "getting user home directory")
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
2018-02-20 23:35:07 +00:00
|
|
|
return filepath.Join(u.HomeDir, BookkeepingDir, PluginDir), nil
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetPlugins returns a list of installed plugins.
|
|
|
|
func GetPlugins() ([]PluginInfo, error) {
|
|
|
|
// To get the list of plugins, simply scan the directory in the usual place.
|
|
|
|
dir, err := GetPluginDir()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
files, err := ioutil.ReadDir(dir)
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now read the file infos and create the plugin infos.
|
|
|
|
var plugins []PluginInfo
|
|
|
|
for _, file := range files {
|
|
|
|
// Skip anything that doesn't look like a plugin.
|
2018-02-19 17:31:00 +00:00
|
|
|
if kind, name, version, ok := tryPlugin(file); ok {
|
2018-02-19 18:58:03 +00:00
|
|
|
plugin := PluginInfo{
|
|
|
|
Name: name,
|
|
|
|
Kind: kind,
|
|
|
|
Version: &version,
|
|
|
|
}
|
2018-04-09 19:51:32 +00:00
|
|
|
if err = plugin.SetFileMetadata(filepath.Join(dir, file.Name())); err != nil {
|
2018-02-19 17:31:00 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2018-02-19 18:58:03 +00:00
|
|
|
plugins = append(plugins, plugin)
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return plugins, nil
|
|
|
|
}
|
|
|
|
|
2018-04-05 23:37:50 +00:00
|
|
|
// GetPluginPath finds a plugin's path by its kind, name, and optional version. It will match the latest version that
|
|
|
|
// is >= the version specified. If no version is supplied, the latest plugin for that given kind/name pair is loaded,
|
|
|
|
// using standard semver sorting rules. A plugin may be overridden entirely by placing it on your $PATH.
|
2018-02-19 18:58:03 +00:00
|
|
|
func GetPluginPath(kind PluginKind, name string, version *semver.Version) (string, string, error) {
|
2018-04-05 23:37:50 +00:00
|
|
|
// If we have a version of the plugin on its $PATH, use it. This supports development scenarios.
|
|
|
|
filename := (&PluginInfo{Kind: kind, Name: name, Version: version}).FilePrefix()
|
|
|
|
if path, err := exec.LookPath(filename); err == nil {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(6).Infof("GetPluginPath(%s, %s, %v): found on $PATH %s", kind, name, version, path)
|
2018-04-05 23:37:50 +00:00
|
|
|
return "", path, nil
|
|
|
|
}
|
2018-02-06 15:20:04 +00:00
|
|
|
|
Look for language plugins next to `pulumi` when probing
When launching plugins today, `pulumi` looks in two places:
1. It looks to see if the plugin in on the $PATH and if so, uses
it. This makes it easy to force a specific version of a resource
provider to be used and is what happens at development time (since
resource providers make their way onto $PATH via GOBIN).
2. If the above fails, it looks in the "plugin cache" in
`~/.pulumi/plugins`. This is the location that `pulumi plugin
install` places plugins.
Unlike resource provider plugins, we don't yet deliver language
plugins via `pulumi plugin install` so the language provider plugins
must be on the `$PATH` to be found. This is okay, because when we ship
the SDK, we include the executables next to `pulumi` itself.
However, if a user chooses to not put `pulumi` on their $PATH, or they
do but it is a symlink to the real `pulumi` binary installed
somewhere, we'd fail to find the language plugins, since they would
not be on the `$PATH`
To address this, when probing for language plugins, also consider
binaries next to the currently running `pulumi` process.
Fixes #1956
2018-11-19 23:07:01 +00:00
|
|
|
// At some point in the future, language plugins will be located in the plugin cache, just like regular plugins
|
|
|
|
// (see pulumi/pulumi#956 for some of the reasons why this isn't the case today). For now, they ship next to the
|
|
|
|
// `pulumi` binary. While we encourage this folder to be on the $PATH (and so the check above would have found
|
|
|
|
// the language plugin) it's possible someone is running `pulumi` with an explicit path on the command line or
|
|
|
|
// has done symlink magic such that `pulumi` is on the path, but the language plugins are not. So, if possible,
|
|
|
|
// look next to the instance of `pulumi` that is running to find this language plugin.
|
|
|
|
if kind == LanguagePlugin {
|
|
|
|
exePath, exeErr := os.Executable()
|
|
|
|
if exeErr == nil {
|
|
|
|
fullPath, fullErr := filepath.EvalSymlinks(exePath)
|
|
|
|
if fullErr == nil {
|
|
|
|
for _, ext := range getCandidateExtensions() {
|
|
|
|
candidate := filepath.Join(filepath.Dir(fullPath), filename+ext)
|
|
|
|
// Let's see if the file is executable. On Windows, os.Stat() returns a mode of "-rw-rw-rw" so on
|
|
|
|
// on windows we just trust the fact that the .exe can actually be launched.
|
|
|
|
if stat, err := os.Stat(candidate); err == nil &&
|
|
|
|
(stat.Mode()&0100 != 0 || runtime.GOOS == windowsGOOS) {
|
|
|
|
logging.V(6).Infof("GetPluginPath(%s, %s, %v): found next to current executable %s",
|
|
|
|
kind, name, version, candidate)
|
|
|
|
|
|
|
|
return "", candidate, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-05 23:37:50 +00:00
|
|
|
// Otherwise, check the plugin cache.
|
|
|
|
plugins, err := GetPlugins()
|
|
|
|
if err != nil {
|
|
|
|
return "", "", errors.Wrapf(err, "loading plugin list")
|
|
|
|
}
|
|
|
|
var match *PluginInfo
|
2018-04-14 01:35:25 +00:00
|
|
|
for _, cur := range plugins {
|
|
|
|
// Since the value of cur changes as we iterate, we can't save a pointer to it. So let's have a local that
|
|
|
|
// we can take a pointer to if this plugin is the best match yet.
|
|
|
|
plugin := cur
|
2018-04-05 23:37:50 +00:00
|
|
|
if plugin.Kind == kind && plugin.Name == name {
|
|
|
|
// Always pick the most recent version of the plugin available. Even if this is an exact match, we
|
|
|
|
// keep on searching just in case there's a newer version available.
|
|
|
|
var m *PluginInfo
|
|
|
|
if match == nil && version == nil {
|
|
|
|
m = &plugin // no existing match, no version spec, take it.
|
|
|
|
} else if match != nil &&
|
|
|
|
(match.Version == nil || (plugin.Version != nil && plugin.Version.GT(*match.Version))) {
|
|
|
|
m = &plugin // existing match, but this plugin is newer, prefer it.
|
|
|
|
} else if version != nil && plugin.Version != nil && plugin.Version.GTE(*version) {
|
|
|
|
m = &plugin // this plugin is >= the version being requested, use it.
|
2018-02-24 00:01:44 +00:00
|
|
|
}
|
2018-02-06 15:20:04 +00:00
|
|
|
|
2018-04-05 23:37:50 +00:00
|
|
|
if m != nil {
|
|
|
|
match = m
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(6).Infof("GetPluginPath(%s, %s, %s): found candidate (#%s)",
|
2018-04-12 22:27:45 +00:00
|
|
|
kind, name, version, match.Version)
|
2018-04-05 23:37:50 +00:00
|
|
|
}
|
2018-02-24 00:01:44 +00:00
|
|
|
}
|
2018-02-19 18:58:03 +00:00
|
|
|
}
|
2018-02-24 00:01:44 +00:00
|
|
|
|
2018-04-05 23:37:50 +00:00
|
|
|
if match != nil {
|
|
|
|
matchDir, err := match.DirPath()
|
|
|
|
if err != nil {
|
|
|
|
return "", "", err
|
|
|
|
}
|
|
|
|
matchPath, err := match.FilePath()
|
|
|
|
if err != nil {
|
|
|
|
return "", "", err
|
|
|
|
}
|
|
|
|
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(6).Infof("GetPluginPath(%s, %s, %v): found in cache at %s", kind, name, version, matchPath)
|
2018-04-05 23:37:50 +00:00
|
|
|
return matchDir, matchPath, nil
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 00:01:44 +00:00
|
|
|
return "", "", nil
|
2018-02-06 15:20:04 +00:00
|
|
|
}
|
|
|
|
|
Look for language plugins next to `pulumi` when probing
When launching plugins today, `pulumi` looks in two places:
1. It looks to see if the plugin in on the $PATH and if so, uses
it. This makes it easy to force a specific version of a resource
provider to be used and is what happens at development time (since
resource providers make their way onto $PATH via GOBIN).
2. If the above fails, it looks in the "plugin cache" in
`~/.pulumi/plugins`. This is the location that `pulumi plugin
install` places plugins.
Unlike resource provider plugins, we don't yet deliver language
plugins via `pulumi plugin install` so the language provider plugins
must be on the `$PATH` to be found. This is okay, because when we ship
the SDK, we include the executables next to `pulumi` itself.
However, if a user chooses to not put `pulumi` on their $PATH, or they
do but it is a symlink to the real `pulumi` binary installed
somewhere, we'd fail to find the language plugins, since they would
not be on the `$PATH`
To address this, when probing for language plugins, also consider
binaries next to the currently running `pulumi` process.
Fixes #1956
2018-11-19 23:07:01 +00:00
|
|
|
// getCandidateExtensions returns a set of file extensions (including the dot seprator) which should be used when
|
|
|
|
// probing for an executable file.
|
|
|
|
func getCandidateExtensions() []string {
|
|
|
|
if runtime.GOOS == windowsGOOS {
|
|
|
|
return []string{".exe", ".cmd"}
|
|
|
|
}
|
|
|
|
|
|
|
|
return []string{""}
|
|
|
|
}
|
|
|
|
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
// pluginRegexp matches plugin filenames: pulumi-KIND-NAME-VERSION[.exe].
|
|
|
|
var pluginRegexp = regexp.MustCompile(
|
2018-02-19 17:31:00 +00:00
|
|
|
"^(?P<Kind>[a-z]+)-" + // KIND
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
"(?P<Name>[a-zA-Z0-9-]*[a-zA-Z0-9])-" + // NAME
|
2018-11-21 23:52:20 +00:00
|
|
|
"v(?P<Version>.*)$") // VERSION
|
2018-02-19 17:31:00 +00:00
|
|
|
|
|
|
|
// tryPlugin returns true if a file is a plugin, and extracts information about it.
|
|
|
|
func tryPlugin(file os.FileInfo) (PluginKind, string, semver.Version, bool) {
|
|
|
|
// Only directories contain plugins.
|
|
|
|
if !file.IsDir() {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(11).Infof("skipping file in plugin directory: %s", file.Name())
|
2018-02-06 15:20:04 +00:00
|
|
|
return "", "", semver.Version{}, false
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Filenames must match the plugin regexp.
|
|
|
|
match := pluginRegexp.FindStringSubmatch(file.Name())
|
|
|
|
if len(match) != len(pluginRegexp.SubexpNames()) {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(11).Infof("skipping plugin %s with missing capture groups: expect=%d, actual=%d",
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
file.Name(), len(pluginRegexp.SubexpNames()), len(match))
|
2018-02-06 15:20:04 +00:00
|
|
|
return "", "", semver.Version{}, false
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
var kind PluginKind
|
|
|
|
var name string
|
|
|
|
var version *semver.Version
|
|
|
|
for i, group := range pluginRegexp.SubexpNames() {
|
|
|
|
v := match[i]
|
|
|
|
switch group {
|
|
|
|
case "Kind":
|
|
|
|
// Skip invalid kinds.
|
|
|
|
if IsPluginKind(v) {
|
|
|
|
kind = PluginKind(v)
|
|
|
|
} else {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(11).Infof("skipping invalid plugin kind: %s", v)
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
case "Name":
|
|
|
|
name = v
|
|
|
|
case "Version":
|
|
|
|
// Skip invalid versions.
|
|
|
|
ver, err := semver.ParseTolerant(v)
|
|
|
|
if err == nil {
|
|
|
|
version = &ver
|
|
|
|
} else {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(11).Infof("skipping invalid plugin version: %s", v)
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If anything was missing or invalid, skip this plugin.
|
|
|
|
if kind == "" || name == "" || version == nil {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(11).Infof("skipping plugin with missing information: kind=%s, name=%s, version=%v",
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
kind, name, version)
|
2018-02-06 15:20:04 +00:00
|
|
|
return "", "", semver.Version{}, false
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:20:04 +00:00
|
|
|
return kind, name, *version, true
|
Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).
Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`. The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).
This commit includes four new CLI commands:
* `pulumi plugin` is the top-level plugin command. It does nothing
but show the help text for associated child commands.
* `pulumi plugin install` can be used to install plugins manually.
If run with no additional arguments, it will compute the set of
plugins used by the current project, and download them all. It
may be run to explicitly download a single plugin, however, by
invoking it as `pulumi plugin install KIND NAME VERSION`. For
example, `pulumi plugin install resource aws v0.9.11`. By default,
this command uses the cloud backend in the usual way to perform the
download, although a separate URL may be given with --cloud-url,
just like all other commands that interact with our backend service.
* `pulumi plugin ls` lists all plugins currently installed in the
plugin cache. It displays some useful statistics, like the size
of the plugin, when it was installed, when it was last used, and
so on. It sorts the display alphabetically by plugin name, and
for plugins with multiple versions, it shows the newest at the top.
The command also summarizes how much disk space is currently being
consumed by the plugin cache. There are no filtering capabilities yet.
* `pulumi plugin prune` will delete plugins from the cache. By
default, when run with no arguments, it will delete everything.
It may be run with additional arguments, KIND, NAME, and VERSION,
each one getting more specific about what it will delete. For
instance, `pulumi plugin prune resource aws` will delete all AWS
plugin versions, while `pulumi plugin prune resource aws <0.9`
will delete all AWS plugins before version 0.9. Unless --yes is
passed, the command will confirm the deletion with a count of how
many plugins will be affected by the command.
We do not yet actually download plugins on demand yet. That will
come in a subsequent change.
2018-02-04 18:51:29 +00:00
|
|
|
}
|
2018-02-19 17:31:00 +00:00
|
|
|
|
|
|
|
// getPluginSize recursively computes how much space is devoted to a given plugin.
|
2018-04-16 16:26:46 +00:00
|
|
|
func getPluginSize(path string) (int64, error) {
|
|
|
|
file, err := os.Stat(path)
|
2018-02-19 17:31:00 +00:00
|
|
|
if err != nil {
|
2018-04-16 16:26:46 +00:00
|
|
|
return 0, nil
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size := int64(0)
|
2018-04-16 16:26:46 +00:00
|
|
|
if file.IsDir() {
|
|
|
|
subs, err := ioutil.ReadDir(path)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
for _, child := range subs {
|
|
|
|
add, err := getPluginSize(filepath.Join(path, child.Name()))
|
2018-02-19 17:31:00 +00:00
|
|
|
if err != nil {
|
2018-04-16 16:26:46 +00:00
|
|
|
return 0, err
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
2018-04-16 16:26:46 +00:00
|
|
|
size += add
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
2018-04-16 16:26:46 +00:00
|
|
|
} else {
|
|
|
|
size += file.Size()
|
2018-02-19 17:31:00 +00:00
|
|
|
}
|
|
|
|
return size, nil
|
|
|
|
}
|