pulumi/pkg/backend/httpstate/backend.go

2133 lines
70 KiB
Go
Raw Permalink Normal View History

Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
// Copyright 2016-2023, Pulumi Corporation.
2018-05-22 19:43:36 +00:00
//
// 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.
package httpstate
import (
"context"
cryptorand "crypto/rand"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"path"
"regexp"
"strconv"
"strings"
"sync"
"time"
opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/browser"
esc_client "github.com/pulumi/esc/cmd/esc/cli/client"
"github.com/pulumi/pulumi/pkg/v3/backend"
"github.com/pulumi/pulumi/pkg/v3/backend/display"
"github.com/pulumi/pulumi/pkg/v3/backend/diy"
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate/client"
sdkDisplay "github.com/pulumi/pulumi/pkg/v3/display"
"github.com/pulumi/pulumi/pkg/v3/engine"
"github.com/pulumi/pulumi/pkg/v3/operations"
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
"github.com/pulumi/pulumi/pkg/v3/secrets"
"github.com/pulumi/pulumi/sdk/v3/go/common/apitype"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag/colors"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/config"
"github.com/pulumi/pulumi/sdk/v3/go/common/slice"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/result"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/retry"
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
)
const (
// defaultAPIEnvVar can be set to override the default cloud chosen, if `--cloud` is not present.
defaultURLEnvVar = "PULUMI_API"
// AccessTokenEnvVar is the environment variable used to bypass a prompt on login.
AccessTokenEnvVar = "PULUMI_ACCESS_TOKEN"
)
Adds Pulumi AI integrations with Pulumi New (#14685) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Now that we support .zip archive sources for Pulumi New, we have all of the API surface we need to provide a full Pulumi New experience using Pulumi AI. This PR introduces a few modes of interacting with Pulumi AI to generate Pulumi projects. - The default `pulumi new` experience now begins with a choice between `ai` and `template` modes - the `template` mode represents the current state of running `pulumi new`, while `ai` provides an interactive experience with Pulumi AI. - The user can iteratively ask questions to improve or change the resulting program - each time a prompt is completed, they are asked to `refine`, `no`, or `yes` their session - `refine` allows a follow-on prompt to be submitted. `no` ends the session without generating a pulumi project, and `yes` generates a Pulumi project from the most recent program returned by Pulumi AI. - Additionally, top-level flags, `--ai` and `--language` are provided to fill in default values for the AI mode. When a prompt is provided with a language, it is automatically submitted to Pulumi AI - if either is missing, the user is prompted for whichever value is missing. Fixes https://github.com/pulumi/pulumi.ai/issues/441 Fixes https://github.com/pulumi/pulumi.ai/issues/443 Fixes https://github.com/pulumi/pulumi.ai/issues/444 Depends on https://github.com/pulumi/pulumi.ai/pull/472 Depends on https://github.com/pulumi/pulumi.ai/pull/507 Depends on https://github.com/pulumi/pulumi.ai/pull/508 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-12-20 22:08:09 +00:00
type PulumiAILanguage string
const (
PulumiAILanguageTypeScript PulumiAILanguage = "TypeScript"
PulumiAILanguageJavaScript PulumiAILanguage = "JavaScript"
PulumiAILanguagePython PulumiAILanguage = "Python"
PulumiAILanguageGo PulumiAILanguage = "Go"
PulumiAILanguageCSharp PulumiAILanguage = "C#"
PulumiAILanguageJava PulumiAILanguage = "Java"
PulumiAILanguageYAML PulumiAILanguage = "YAML"
)
var pulumiAILanguageMap = map[string]PulumiAILanguage{
"typescript": PulumiAILanguageTypeScript,
"javascript": PulumiAILanguageJavaScript,
"python": PulumiAILanguagePython,
"go": PulumiAILanguageGo,
"c#": PulumiAILanguageCSharp,
"java": PulumiAILanguageJava,
"yaml": PulumiAILanguageYAML,
}
// All of the languages supported by Pulumi AI.
var PulumiAILanguageOptions = []PulumiAILanguage{
PulumiAILanguageTypeScript,
PulumiAILanguageJavaScript,
PulumiAILanguagePython,
PulumiAILanguageGo,
PulumiAILanguageCSharp,
PulumiAILanguageJava,
PulumiAILanguageYAML,
}
// A natural language list of languages supported by Pulumi AI.
const PulumiAILanguagesClause = "TypeScript, JavaScript, Python, Go, C#, Java, or YAML"
func (e *PulumiAILanguage) String() string {
return string(*e)
}
func (e *PulumiAILanguage) Set(v string) error {
value, ok := pulumiAILanguageMap[strings.ToLower(v)]
if !ok {
return fmt.Errorf("must be one of %s", PulumiAILanguagesClause)
}
*e = value
return nil
}
func (e *PulumiAILanguage) Type() string {
return "pulumiAILanguage"
}
type AIPromptRequestBody struct {
Language PulumiAILanguage `json:"language"`
Instructions string `json:"instructions"`
ResponseMode string `json:"responseMode"`
ConversationID string `json:"conversationId"`
ConnectionID string `json:"connectionId"`
}
// Name validation rules enforced by the Pulumi Service.
var stackOwnerRegexp = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9-_]{1,38}[a-zA-Z0-9]$")
// DefaultURL returns the default cloud URL. This may be overridden using the PULUMI_API environment
// variable. If no override is found, and we are authenticated with a cloud, choose that. Otherwise,
// we will default to the https://api.pulumi.com/ endpoint.
func DefaultURL() string {
return ValueOrDefaultURL("")
}
// ValueOrDefaultURL returns the value if specified, or the default cloud URL otherwise.
func ValueOrDefaultURL(cloudURL string) string {
// If we have a cloud URL, just return it.
if cloudURL != "" {
return strings.TrimSuffix(cloudURL, "/")
}
// Otherwise, respect the PULUMI_API override.
if cloudURL := os.Getenv(defaultURLEnvVar); cloudURL != "" {
return cloudURL
}
// If that didn't work, see if we have a current cloud, and use that. Note we need to be careful
// to ignore the diy cloud.
if creds, err := workspace.GetStoredCredentials(); err == nil {
if creds.Current != "" && !diy.IsDIYBackendURL(creds.Current) {
return creds.Current
}
}
// If none of those led to a cloud URL, simply return the default.
return PulumiCloudURL
}
// Backend extends the base backend interface with specific information about cloud backends.
type Backend interface {
backend.Backend
CloudURL() string
StackConsoleURL(stackRef backend.StackReference) (string, error)
Client() *client.Client
RunDeployment(ctx context.Context, stackRef backend.StackReference, req apitype.CreateDeploymentRequest,
opts display.Options, deploymentInitiator string, streamDeploymentLogs bool) error
Adds two new CLI features - search and AI search (#13611) Adds initial pulumi search implementation <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/13489 Fixes https://github.com/pulumi/pulumi/issues/12868 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-08-21 15:06:46 +00:00
// Queries the backend for resources based on the given query parameters.
Search(
ctx context.Context, orgName string, queryParams *apitype.PulumiQueryRequest,
) (*apitype.ResourceSearchResponse, error)
[org search] Adds both the display of and the ability to open search results URLs (#13879) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Displays to users a copyable URL to view org search results in Pulumi Cloud as well as a `--web` flag to automatically open those results for them. Fixes https://github.com/pulumi/pulumi.ai/issues/207 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-09-11 16:33:56 +00:00
NaturalLanguageSearch(
ctx context.Context, orgName string, query string,
) (*apitype.ResourceSearchResponse, error)
Adds Pulumi AI integrations with Pulumi New (#14685) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Now that we support .zip archive sources for Pulumi New, we have all of the API surface we need to provide a full Pulumi New experience using Pulumi AI. This PR introduces a few modes of interacting with Pulumi AI to generate Pulumi projects. - The default `pulumi new` experience now begins with a choice between `ai` and `template` modes - the `template` mode represents the current state of running `pulumi new`, while `ai` provides an interactive experience with Pulumi AI. - The user can iteratively ask questions to improve or change the resulting program - each time a prompt is completed, they are asked to `refine`, `no`, or `yes` their session - `refine` allows a follow-on prompt to be submitted. `no` ends the session without generating a pulumi project, and `yes` generates a Pulumi project from the most recent program returned by Pulumi AI. - Additionally, top-level flags, `--ai` and `--language` are provided to fill in default values for the AI mode. When a prompt is provided with a language, it is automatically submitted to Pulumi AI - if either is missing, the user is prompted for whichever value is missing. Fixes https://github.com/pulumi/pulumi.ai/issues/441 Fixes https://github.com/pulumi/pulumi.ai/issues/443 Fixes https://github.com/pulumi/pulumi.ai/issues/444 Depends on https://github.com/pulumi/pulumi.ai/pull/472 Depends on https://github.com/pulumi/pulumi.ai/pull/507 Depends on https://github.com/pulumi/pulumi.ai/pull/508 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-12-20 22:08:09 +00:00
PromptAI(ctx context.Context, requestBody AIPromptRequestBody) (*http.Response, error)
}
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
type cloudBackend struct {
2023-02-17 10:39:17 +00:00
d diag.Sink
url string
client *client.Client
escClient esc_client.Client
2023-02-17 10:39:17 +00:00
capabilities func(context.Context) capabilities
// The current project, if any.
currentProject *workspace.Project
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
// Assert we implement the backend.Backend and backend.SpecificDeploymentExporter interfaces.
var _ backend.SpecificDeploymentExporter = &cloudBackend{}
// New creates a new Pulumi backend for the given cloud API URL and token.
func New(d diag.Sink, cloudURL string, project *workspace.Project, insecure bool) (Backend, error) {
cloudURL = ValueOrDefaultURL(cloudURL)
account, err := workspace.GetAccount(cloudURL)
if err != nil {
return nil, fmt.Errorf("getting stored credentials: %w", err)
}
apiToken := account.AccessToken
apiClient := client.NewClient(cloudURL, apiToken, insecure, d)
escClient := esc_client.New(client.UserAgent(), cloudURL, apiToken, insecure)
capabilities := detectCapabilities(d, apiClient)
return &cloudBackend{
d: d,
url: cloudURL,
client: apiClient,
escClient: escClient,
capabilities: capabilities,
currentProject: project,
}, nil
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
// loginWithBrowser uses a web-browser to log into the cloud and returns the cloud backend for it.
func loginWithBrowser(
ctx context.Context,
cloudURL string,
insecure bool,
command string,
welcome func(display.Options),
current bool,
opts display.Options,
) (*workspace.Account, error) {
// Locally, we generate a nonce and spin up a web server listening on a random port on localhost. We then open a
// browser to a special endpoint on the Pulumi.com console, passing the generated nonce as well as the port of the
// webserver we launched. This endpoint does the OAuth flow and when it completes, redirects to localhost passing
// the nonce and the pulumi access token we created as part of the OAuth flow. If the nonces match, we set the
// access token that was passed to us and the redirect to a special welcome page on Pulumi.com
loginURL := cloudConsoleURL(cloudURL, "cli-login")
finalWelcomeURL := cloudConsoleURL(cloudURL, "welcome", "cli")
if loginURL == "" || finalWelcomeURL == "" {
return nil, errors.New("could not determine login url")
}
// Listen on localhost, have the kernel pick a random port for us
c := make(chan string)
l, err := net.Listen("tcp", "127.0.0.1:")
if err != nil {
return nil, fmt.Errorf("could not start listener: %w", err)
}
// Extract the port
_, port, err := net.SplitHostPort(l.Addr().String())
if err != nil {
return nil, fmt.Errorf("could not determine port: %w", err)
}
// Generate a nonce we'll send with the request.
nonceBytes := make([]byte, 32)
_, err = cryptorand.Read(nonceBytes)
contract.AssertNoErrorf(err, "could not get random bytes")
nonce := hex.EncodeToString(nonceBytes)
u, err := url.Parse(loginURL)
contract.AssertNoErrorf(err, "error parsing login url: %s", loginURL)
// Generate a description to associate with the access token we'll generate, for display on the Account Settings
// page.
var tokenDescription string
if host, hostErr := os.Hostname(); hostErr == nil {
tokenDescription = fmt.Sprintf("Generated by %s login on %s at %s", command, host, time.Now().Format(time.RFC822))
} else {
tokenDescription = fmt.Sprintf("Generated by %s login at %s", command, time.Now().Format(time.RFC822))
}
// Pass our state around as query parameters on the URL we'll open the user's preferred browser to
q := u.Query()
q.Add("cliSessionPort", port)
q.Add("cliSessionNonce", nonce)
q.Add("cliSessionDescription", tokenDescription)
if command != "pulumi" {
q.Add("cliCommand", command)
}
u.RawQuery = q.Encode()
// Start the webserver to listen to handle the response
go serveBrowserLoginServer(l, nonce, finalWelcomeURL, c)
// Launch the web browser and navigate to the login URL.
if openErr := browser.OpenURL(u.String()); openErr != nil {
fmt.Printf("We couldn't launch your web browser for some reason. Please visit:\n\n%s\n\n"+
"to finish the login process.", u)
} else {
fmt.Println("We've launched your web browser to complete the login process.")
}
fmt.Println("\nWaiting for login to complete...")
accessToken := <-c
username, organizations, tokenInfo, err := client.NewClient(
cloudURL, accessToken, insecure, cmdutil.Diag()).GetPulumiAccountDetails(ctx)
if err != nil {
return nil, err
}
// Save the token and return the backend
account := workspace.Account{
AccessToken: accessToken,
Username: username,
Organizations: organizations,
LastValidatedAt: time.Now(),
Insecure: insecure,
TokenInformation: tokenInfo,
}
if err = workspace.StoreAccount(cloudURL, account, current); err != nil {
return nil, err
}
// Welcome the user since this was an interactive login.
if welcome != nil {
welcome(opts)
}
return &account, nil
}
// LoginManager provides a slim wrapper around functions related to backend logins.
type LoginManager interface {
// Current returns the current cloud backend if one is already logged in.
Current(ctx context.Context, cloudURL string, insecure, setCurrent bool) (*workspace.Account, error)
// Login logs into the target cloud URL and returns the cloud backend for it.
Login(
ctx context.Context,
cloudURL string,
insecure bool,
command string,
message string,
welcome func(display.Options),
current bool,
opts display.Options,
) (*workspace.Account, error)
}
// NewLoginManager returns a LoginManager for handling backend logins.
func NewLoginManager() LoginManager {
return newLoginManager()
}
// newLoginManager creates a new LoginManager for handling logins. It is a variable instead of a regular
// function so it can be set to a different implementation at runtime, if necessary.
var newLoginManager = func() LoginManager {
return defaultLoginManager{}
}
type defaultLoginManager struct{}
// Current returns the current cloud backend if one is already logged in.
func (m defaultLoginManager) Current(
ctx context.Context,
cloudURL string,
insecure bool,
setCurrent bool,
) (*workspace.Account, error) {
cloudURL = ValueOrDefaultURL(cloudURL)
// If we have a saved access token, and it is valid, use it.
existingAccount, err := workspace.GetAccount(cloudURL)
if err == nil && existingAccount.AccessToken != "" {
// If the account was last verified less than an hour ago, assume the token is valid.
valid := true
username := existingAccount.Username
organizations := existingAccount.Organizations
tokenInfo := existingAccount.TokenInformation
if username == "" || existingAccount.LastValidatedAt.Add(1*time.Hour).Before(time.Now()) {
valid, username, organizations, tokenInfo, err = IsValidAccessToken(
ctx, cloudURL, insecure, existingAccount.AccessToken)
if err != nil {
return nil, err
}
existingAccount.LastValidatedAt = time.Now()
}
if valid {
// Save the token. While it hasn't changed this will update the current cloud we are logged into, as well.
existingAccount.Username = username
existingAccount.Organizations = organizations
existingAccount.TokenInformation = tokenInfo
existingAccount.Insecure = insecure
if err = workspace.StoreAccount(cloudURL, existingAccount, setCurrent); err != nil {
return nil, err
}
return &existingAccount, nil
}
}
// We intentionally don't accept command-line args for the user's access token. Having it in
// .bash_history is not great, and specifying it via flag isn't of much use.
accessToken := os.Getenv(AccessTokenEnvVar)
if accessToken == "" {
// No access token available, this isn't an error per-se but we don't have a backend
return nil, nil
}
// If there's already a token from the environment, use it.
_, err = fmt.Fprintf(os.Stderr, "Logging in using access token from %s\n", AccessTokenEnvVar)
contract.IgnoreError(err)
// Try and use the credentials to see if they are valid.
valid, username, organizations, tokenInfo, err := IsValidAccessToken(ctx, cloudURL, insecure, accessToken)
if err != nil {
return nil, err
} else if !valid {
Enable perfsprint linter (#14813) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Prompted by a comment in another review: https://github.com/pulumi/pulumi/pull/14654#discussion_r1419995945 This lints that we don't use `fmt.Errorf` when `errors.New` will suffice, it also covers a load of other cases where `Sprintf` is sub-optimal. Most of these edits were made by running `perfsprint --fix`. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-12-12 12:19:42 +00:00
return nil, errors.New("invalid access token")
}
// Save them.
account := workspace.Account{
AccessToken: accessToken,
Username: username,
Organizations: organizations,
TokenInformation: tokenInfo,
LastValidatedAt: time.Now(),
Insecure: insecure,
}
if err = workspace.StoreAccount(cloudURL, account, setCurrent); err != nil {
return nil, err
}
return &account, nil
}
// Login logs into the target cloud URL and returns the cloud backend for it.
func (m defaultLoginManager) Login(
ctx context.Context,
cloudURL string,
insecure bool,
command string,
message string,
welcome func(display.Options),
setCurrent bool,
opts display.Options,
) (*workspace.Account, error) {
current, err := m.Current(ctx, cloudURL, insecure, setCurrent)
if err != nil {
return nil, err
}
if current != nil {
return current, nil
}
cloudURL = ValueOrDefaultURL(cloudURL)
var accessToken string
accountLink := cloudConsoleURL(cloudURL, "account", "tokens")
if !cmdutil.Interactive() {
// If interactive mode isn't enabled, the only way to specify a token is through the environment variable.
// Fail the attempt to login.
return nil, fmt.Errorf("%s must be set for login during non-interactive CLI sessions", AccessTokenEnvVar)
}
// If no access token is available from the environment, and we are interactive, prompt and offer to
// open a browser to make it easy to generate and use a fresh token.
line1 := "Manage your " + message + " by logging in."
line1len := len(line1)
line1 = colors.Highlight(line1, message, colors.Underline+colors.Bold)
fmt.Printf(opts.Color.Colorize(line1) + "\n")
maxlen := line1len
line2 := fmt.Sprintf("Run `%s login --help` for alternative login options.", command)
line2len := len(line2)
fmt.Printf(opts.Color.Colorize(line2) + "\n")
if line2len > maxlen {
maxlen = line2len
}
// In the case where we could not construct a link to the pulumi console based on the API server's hostname,
// don't offer magic log-in or text about where to find your access token.
if accountLink == "" {
for {
if accessToken, err = cmdutil.ReadConsoleNoEcho("Enter your access token"); err != nil {
return nil, err
}
if accessToken != "" {
break
}
}
} else {
Enable perfsprint linter (#14813) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Prompted by a comment in another review: https://github.com/pulumi/pulumi/pull/14654#discussion_r1419995945 This lints that we don't use `fmt.Errorf` when `errors.New` will suffice, it also covers a load of other cases where `Sprintf` is sub-optimal. Most of these edits were made by running `perfsprint --fix`. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-12-12 12:19:42 +00:00
line3 := "Enter your access token from " + accountLink
line3len := len(line3)
line3 = colors.Highlight(line3, "access token", colors.BrightCyan+colors.Bold)
line3 = colors.Highlight(line3, accountLink, colors.BrightBlue+colors.Underline+colors.Bold)
fmt.Printf(opts.Color.Colorize(line3) + "\n")
if line3len > maxlen {
maxlen = line3len
}
line4 := " or hit <ENTER> to log in using your browser"
var padding string
if pad := maxlen - len(line4); pad > 0 {
padding = strings.Repeat(" ", pad)
}
line4 = colors.Highlight(line4, "<ENTER>", colors.BrightCyan+colors.Bold)
if accessToken, err = cmdutil.ReadConsoleNoEcho(opts.Color.Colorize(line4) + padding); err != nil {
return nil, err
}
if accessToken == "" {
return loginWithBrowser(ctx, cloudURL, insecure, command, welcome, setCurrent, opts)
}
// Welcome the user since this was an interactive login.
if welcome != nil {
welcome(opts)
}
}
// Try and use the credentials to see if they are valid.
valid, username, organizations, tokenInfo, err := IsValidAccessToken(ctx, cloudURL, insecure, accessToken)
if err != nil {
return nil, err
} else if !valid {
Enable perfsprint linter (#14813) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Prompted by a comment in another review: https://github.com/pulumi/pulumi/pull/14654#discussion_r1419995945 This lints that we don't use `fmt.Errorf` when `errors.New` will suffice, it also covers a load of other cases where `Sprintf` is sub-optimal. Most of these edits were made by running `perfsprint --fix`. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-12-12 12:19:42 +00:00
return nil, errors.New("invalid access token")
}
// Save them.
account := workspace.Account{
AccessToken: accessToken,
Username: username,
Organizations: organizations,
TokenInformation: tokenInfo,
LastValidatedAt: time.Now(),
Insecure: insecure,
}
if err = workspace.StoreAccount(cloudURL, account, setCurrent); err != nil {
return nil, err
}
return &account, nil
}
// WelcomeUser prints a Welcome to Pulumi message.
func WelcomeUser(opts display.Options) {
fmt.Printf(`
%s
Pulumi helps you create, deploy, and manage infrastructure on any cloud using
your favorite language. You can get started today with Pulumi at:
https://www.pulumi.com/docs/get-started/
%s Resources you create with Pulumi are given unique names (a randomly
generated suffix) by default. To learn more about auto-naming or customizing resource
names see https://www.pulumi.com/docs/intro/concepts/resources/#autonaming.
`,
opts.Color.Colorize(colors.SpecHeadline+"Welcome to Pulumi!"+colors.Reset),
2023-02-16 00:32:38 +00:00
opts.Color.Colorize(colors.SpecSubHeadline+"Tip:"+colors.Reset))
}
func (b *cloudBackend) StackConsoleURL(stackRef backend.StackReference) (string, error) {
stackID, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return "", err
}
path := b.cloudConsoleStackPath(stackID)
url := b.CloudConsoleURL(path)
if url == "" {
return "", errors.New("could not determine cloud console URL")
}
return url, nil
}
func (b *cloudBackend) Name() string {
if b.url == PulumiCloudURL {
return "pulumi.com"
}
return b.url
}
func (b *cloudBackend) URL() string {
user, _, _, err := b.CurrentUser()
if err != nil {
return cloudConsoleURL(b.url)
}
return cloudConsoleURL(b.url, user)
}
func (b *cloudBackend) SetCurrentProject(project *workspace.Project) {
b.currentProject = project
}
func (b *cloudBackend) CurrentUser() (string, []string, *workspace.TokenInformation, error) {
return b.currentUser(context.Background())
}
func (b *cloudBackend) currentUser(ctx context.Context) (string, []string, *workspace.TokenInformation, error) {
account, err := workspace.GetAccount(b.CloudURL())
if err != nil {
return "", nil, nil, err
}
if account.Username != "" {
logging.V(1).Infof("found username for access token")
return account.Username, account.Organizations, account.TokenInformation, nil
}
logging.V(1).Infof("no username for access token")
return b.client.GetPulumiAccountDetails(ctx)
}
func (b *cloudBackend) CloudURL() string { return b.url }
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
func (b *cloudBackend) parsePolicyPackReference(s string) (backend.PolicyPackReference, error) {
split := strings.Split(s, "/")
var orgName string
var policyPackName string
switch len(split) {
case 2:
orgName = split[0]
policyPackName = split[1]
default:
return nil, fmt.Errorf("could not parse policy pack name '%s'; must be of the form "+
"<org-name>/<policy-pack-name>", s)
}
if orgName == "" {
currentUser, _, _, userErr := b.CurrentUser()
if userErr != nil {
return nil, userErr
}
orgName = currentUser
}
2020-02-26 17:45:39 +00:00
return newCloudBackendPolicyPackReference(b.CloudConsoleURL(), orgName, tokens.QName(policyPackName)), nil
}
func (b *cloudBackend) GetPolicyPack(ctx context.Context, policyPack string,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
d diag.Sink,
) (backend.PolicyPack, error) {
policyPackRef, err := b.parsePolicyPackReference(policyPack)
if err != nil {
return nil, err
}
return &cloudPolicyPack{
2020-02-26 17:45:39 +00:00
ref: newCloudBackendPolicyPackReference(b.CloudConsoleURL(),
2019-07-10 17:55:42 +00:00
policyPackRef.OrgName(), policyPackRef.Name()),
b: b,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
cl: b.client,
}, nil
}
func (b *cloudBackend) ListPolicyGroups(ctx context.Context, orgName string, inContToken backend.ContinuationToken) (
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
apitype.ListPolicyGroupsResponse, backend.ContinuationToken, error,
) {
return b.client.ListPolicyGroups(ctx, orgName, inContToken)
2020-01-16 20:04:51 +00:00
}
func (b *cloudBackend) ListPolicyPacks(ctx context.Context, orgName string, inContToken backend.ContinuationToken) (
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
apitype.ListPolicyPacksResponse, backend.ContinuationToken, error,
) {
return b.client.ListPolicyPacks(ctx, orgName, inContToken)
2020-01-16 20:04:51 +00:00
}
func (b *cloudBackend) SupportsTags() bool {
return true
}
func (b *cloudBackend) SupportsOrganizations() bool {
return true
}
stack ls: remove misleading updateInProgress output for file backend (#14309) File backends currently do not support indicating whether an operation is currently in progress or not. In the `stack ls --json` output we always end up with a "updateInProgress = false" field, even when an update is in progress. This is misleading. Disable showing this erroneous and misleading output. Fixes #10677 Based on Luke's comments in that issue, I believe we should merge this as bug fix for the issue, and then open a separate feature request tracking the implementation of tracking whether an update is in progress in the file backend. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-10-27 07:33:07 +00:00
func (b *cloudBackend) SupportsProgress() bool {
return true
}
func (b *cloudBackend) SupportsDeployments() bool {
return true
}
// qualifiedStackReference describes a qualified stack on the Pulumi Service. The Owner or Project
// may be "" if unspecified, e.g. "pulumi/production" specifies the Owner and Name, but not the
// Project. We infer the missing data and try to make things work as best we can in ParseStackReference.
type qualifiedStackReference struct {
Owner string
Project string
Name string
}
// parseStackName parses the stack name into a potentially qualifiedStackReference. Any omitted
// portions will be left as "". For example:
//
// "alpha" - will just set the Name, but ignore Owner and Project.
// "alpha/beta" - will set the Owner and Name, but not Project.
// "alpha/beta/gamma" - will set Owner, Name, and Project.
func (b *cloudBackend) parseStackName(s string) (qualifiedStackReference, error) {
var q qualifiedStackReference
split := strings.Split(s, "/")
2019-01-25 17:48:08 +00:00
switch len(split) {
case 1:
q.Name = split[0]
2019-01-25 17:48:08 +00:00
case 2:
q.Owner = split[0]
q.Name = split[1]
2019-01-25 17:48:08 +00:00
case 3:
q.Owner = split[0]
q.Project = split[1]
q.Name = split[2]
2019-01-25 17:48:08 +00:00
default:
return qualifiedStackReference{}, fmt.Errorf("could not parse stack name '%s'", s)
}
return q, nil
}
func (b *cloudBackend) ParseStackReference(s string) (backend.StackReference, error) {
// Parse the input as a qualified stack name.
qualifiedName, err := b.parseStackName(s)
if err != nil {
return nil, err
}
// If the provided stack name didn't include the Owner or Project, infer them from the
// local environment.
if qualifiedName.Owner == "" {
// if the qualifiedName doesn't include an owner then let's check to see if there is a default org which *will*
// be the stack owner. If there is no defaultOrg, then we revert to checking the CurrentUser
defaultOrg, err := workspace.GetBackendConfigDefaultOrg(b.currentProject)
if err != nil {
return nil, err
}
if defaultOrg != "" {
qualifiedName.Owner = defaultOrg
} else {
currentUser, _, _, userErr := b.CurrentUser()
if userErr != nil {
return nil, userErr
}
qualifiedName.Owner = currentUser
}
}
if qualifiedName.Project == "" {
if b.currentProject == nil {
Refine the error message when a full stack name is not supplied (#16313) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description Refine the error message when a full stack name is not supplied outside a project directory Context: 1. Open a brand-new clean directory that is not a child directory to any Pulumi program. 2. Run `pulumi stack init dev` 3. CLI doesn't have a project name at this point, because it has not Pulumi.yaml. So, the user needs to supply the full name. Fixes https://github.com/pulumi/pulumi/issues/15967 ## Checklist - [ ] I have run `make tidy` to update any new dependencies - [ ] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-06-03 16:38:25 +00:00
return nil, errors.New("no current project found, pass the fully qualified stack name (org/project/stack)")
}
qualifiedName.Project = b.currentProject.Name.String()
}
Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
parsedName, err := tokens.ParseStackName(qualifiedName.Name)
if err != nil {
return nil, err
}
return cloudBackendReference{
owner: qualifiedName.Owner,
project: tokens.Name(qualifiedName.Project),
Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
name: parsedName,
b: b,
2018-04-18 18:25:16 +00:00
}, nil
}
func (b *cloudBackend) ValidateStackName(s string) error {
qualifiedName, err := b.parseStackName(s)
if err != nil {
return err
}
// The Pulumi Service enforces specific naming restrictions for organizations,
// projects, and stacks. Though ignore any values that need to be inferred later.
if qualifiedName.Owner != "" {
if err := validateOwnerName(qualifiedName.Owner); err != nil {
return err
}
}
if qualifiedName.Project != "" {
if err := validateProjectName(qualifiedName.Project); err != nil {
return err
}
}
Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
_, err = tokens.ParseStackName(qualifiedName.Name)
return err
}
// validateOwnerName checks if a stack owner name is valid. An "owner" is simply the namespace
// a stack may exist within, which for the Pulumi Service is the user account or organization.
func validateOwnerName(s string) error {
if !stackOwnerRegexp.MatchString(s) {
return errors.New("invalid stack owner")
}
return nil
}
// validateProjectName checks if a project name is valid, returning a user-suitable error if needed.
//
// NOTE: Be careful when requiring a project name be valid. The Pulumi.yaml file may contain
// an invalid project name like "r@bid^W0MBAT!!", but we try to err on the side of flexibility by
// implicitly "cleaning" the project name before we send it to the Pulumi Service. So when we go
// to make HTTP requests, we use a more palitable name like "r_bid_W0MBAT__".
//
// The projects canonical name will be the sanitized "r_bid_W0MBAT__" form, but we do not require the
// Pulumi.yaml file be updated.
//
// So we should only call validateProject name when creating _new_ stacks or creating _new_ projects.
// We should not require that project names be valid when reading what is in the current workspace.
func validateProjectName(s string) error {
return tokens.ValidateProjectName(s)
}
// CloudConsoleURL returns a link to the cloud console with the given path elements. If a console link cannot be
// created, we return the empty string instead (this can happen if the endpoint isn't a recognized pattern).
func (b *cloudBackend) CloudConsoleURL(paths ...string) string {
return cloudConsoleURL(b.CloudURL(), paths...)
}
// serveBrowserLoginServer hosts the server that completes the browser based login flow.
func serveBrowserLoginServer(l net.Listener, expectedNonce string, destinationURL string, c chan<- string) {
handler := func(res http.ResponseWriter, req *http.Request) {
tok := req.URL.Query().Get("accessToken")
nonce := req.URL.Query().Get("nonce")
if tok == "" || nonce != expectedNonce {
res.WriteHeader(400)
return
}
http.Redirect(res, req, destinationURL, http.StatusTemporaryRedirect)
c <- tok
}
mux := &http.ServeMux{}
mux.HandleFunc("/", handler)
contract.IgnoreError(http.Serve(l, mux)) //nolint:gosec
}
// CloudConsoleStackPath returns the stack path components for getting to a stack in the cloud console. This path
// must, of course, be combined with the actual console base URL by way of the CloudConsoleURL function above.
func (b *cloudBackend) cloudConsoleStackPath(stackID client.StackIdentifier) string {
Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
return path.Join(stackID.Owner, stackID.Project, stackID.Stack.String())
}
func inferOrg(ctx context.Context,
getDefaultOrg func() (string, error),
getUserOrg func() (string, error),
) (string, error) {
orgName, err := getDefaultOrg()
if err != nil || orgName == "" {
// Fallback to using the current user.
orgName, err = getUserOrg()
if err != nil || orgName == "" {
return "", errors.New("could not determine organization name")
}
}
return orgName, nil
}
// DoesProjectExist returns true if a project with the given name exists in this backend, or false otherwise.
func (b *cloudBackend) DoesProjectExist(ctx context.Context, orgName string, projectName string) (bool, error) {
if orgName != "" {
return b.client.DoesProjectExist(ctx, orgName, projectName)
}
getDefaultOrg := func() (string, error) {
return workspace.GetBackendConfigDefaultOrg(nil)
}
getUserOrg := func() (string, error) {
orgName, _, _, err := b.currentUser(ctx)
return orgName, err
}
orgName, err := inferOrg(ctx, getDefaultOrg, getUserOrg)
if err != nil {
return false, err
}
return b.client.DoesProjectExist(ctx, orgName, projectName)
}
func (b *cloudBackend) GetStack(ctx context.Context, stackRef backend.StackReference) (backend.Stack, error) {
stackID, err := b.getCloudStackIdentifier(stackRef)
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
if err != nil {
return nil, err
}
// GetStack is typically the initial call to a series of calls to the backend. Although logically unrelated,
// this is a good time to start detecting capabilities so that capability request is not on the critical path.
go b.capabilities(ctx)
stack, err := b.client.GetStack(ctx, stackID)
if err != nil {
// If this was a 404, return nil, nil as per this method's contract.
if errResp, ok := err.(*apitype.ErrorResponse); ok && errResp.Code == http.StatusNotFound {
return nil, nil
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
return nil, err
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
return newStack(stack, b), nil
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
// Confirm the specified stack's project doesn't contradict the Pulumi.yaml of the current project.
// if the CWD is not in a Pulumi project,
2022-09-14 02:12:02 +00:00
//
// does not contradict
//
// if the project name in Pulumi.yaml is "foo".
2022-09-14 02:12:02 +00:00
//
// a stack with a name of foo/bar/foo should not work.
func currentProjectContradictsWorkspace(project *workspace.Project, stack client.StackIdentifier) bool {
if project == nil {
return false
}
return project.Name.String() != stack.Project
}
func (b *cloudBackend) CreateStack(
ctx context.Context, stackRef backend.StackReference, root string,
opts *backend.CreateStackOptions,
) (
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
backend.Stack, error,
) {
if opts == nil {
opts = &backend.CreateStackOptions{}
}
stackID, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return nil, err
}
if currentProjectContradictsWorkspace(b.currentProject, stackID) {
return nil, fmt.Errorf("provided project name %q doesn't match Pulumi.yaml", stackID.Project)
}
// TODO: This should load project config and pass it as the last parameter to GetEnvironmentTagsForCurrentStack.
tags, err := backend.GetEnvironmentTagsForCurrentStack(root, b.currentProject, nil)
if err != nil {
return nil, fmt.Errorf("getting stack tags: %w", err)
}
apistack, err := b.client.CreateStack(ctx, stackID, tags, opts.Teams)
if err != nil {
// Wire through well-known error types.
if errResp, ok := err.(*apitype.ErrorResponse); ok && errResp.Code == http.StatusConflict {
// A 409 error response is returned when per-stack organizations are over their limit,
// so we need to look at the message to differentiate.
if strings.Contains(errResp.Message, "already exists") {
return nil, &backend.StackAlreadyExistsError{StackName: stackID.String()}
}
if strings.Contains(errResp.Message, "you are using") {
return nil, &backend.OverStackLimitError{Message: errResp.Message}
}
}
Make some stack-related CLI improvements (#947) This change includes a handful of stack-related CLI formatting improvements that I've been noodling on in the background for a while, based on things that tend to trip up demos and the inner loop workflow. This includes: * If `pulumi stack select` is run by itself, use an interactive CLI menu to let the user select an existing stack, or choose to create a new one. This looks as follows $ pulumi stack select Please choose a stack, or choose to create a new one: abcdef babblabblabble > currentlyselected defcon <create a new stack> and is navigated in the usual way (key up, down, enter). * If a stack name is passed that does not exist, prompt the user to ask whether s/he wants to create one on-demand. This hooks interesting moments in time, like `pulumi stack select foo`, and cuts down on the need to run additional commands. * If a current stack is required, but none is currently selected, then pop the same interactive menu shown above to select one. Depending on the command being run, we may or may not show the option to create a new stack (e.g., that doesn't make much sense when you're running `pulumi destroy`, but might when you're running `pulumi stack`). This again lets you do with a single command what would have otherwise entailed an error with multiple commands to recover from it. * If you run `pulumi stack init` without any additional arguments, we interactively prompt for the stack name. Before, we would error and you'd then need to run `pulumi stack init <name>`. * Colorize some things nicely; for example, now all prompts will by default become bright white.
2018-02-16 23:03:54 +00:00
return nil, err
}
stack := newStack(apistack, b)
Make a smattering of CLI UX improvements Since I was digging around over the weekend after the change to move away from light black, and the impact it had on less important information showing more prominently than it used to, I took a step back and did a deeper tidying up of things. Another side goal of this exercise was to be a little more respectful of terminal width; when we could say things with fewer words, I did so. * Stylize the preview/update summary differently, so that it stands out as a section. Also highlight the total changes with bold -- it turns out this has a similar effect to the bright white colorization, just without the negative effects on e.g. white terminals. * Eliminate some verbosity in the phrasing of change summaries. * Make all heading sections stylized consistently. This includes the color (bright magenta) and the vertical spacing (always a newline separating headings). We were previously inconsistent on this (e.g., outputs were under "---outputs---"). Now the headings are: Previewing (etc), Diagnostics, Outputs, Resources, Duration, and Permalink. * Fix an issue where we'd parent things to "global" until the stack object later showed up. Now we'll simply mock up a stack resource. * Don't show messages like "no change" or "unchanged". Prior to the light black removal, these faded into the background of the terminal. Now they just clutter up the display. Similar to the elision of "*" for OpSames in a prior commit, just leave these out. Now anything that's written is actually a meaningful status for the user to note. * Don't show the "3 info messages," etc. summaries in the Info column while an update is ongoing. Instead, just show the latest line. This is more respectful of width -- I often find that the important messages scroll off the right of my screen before this change. For discussion: - I actually wonder if we should eliminate the summary altogether and always just show the latest line. Or even blank it out. The summary feels better suited for the Diagnostics section, and the Status concisely tells us how a resource's update ended up (failed, succeeded, etc). - Similarly, I question the idea of showing only the "worst" message. I'd vote for always showing the latest, and again leaving it to the Status column for concisely telling the user about the final state a resource ended up in. * Stop prepending "info: " to every stdout/stderr message. It adds no value, clutters up the display, and worsens horizontal usage. * Lessen the verbosity of update headline messages, so we now instead of e.g. "Previewing update of stack 'x':", we just say "Previewing update (x):". * Eliminate vertical whitespace in the Diagnostics section. Every independent console.out previously was separated by an entire newline, which made the section look cluttered to my eyes. These are just streams of logs, there's no reason for the extra newlines. * Colorize the resource headers in the Diagnostic section light blue. Note that this will change various test baselines, which I will update next. I didn't want those in the same commit.
2018-09-24 15:31:19 +00:00
fmt.Printf("Created stack '%s'\n", stack.Ref())
return stack, nil
}
func (b *cloudBackend) ListStacks(
ctx context.Context, filter backend.ListStacksFilter, inContToken backend.ContinuationToken) (
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
[]backend.StackSummary, backend.ContinuationToken, error,
) {
// Sanitize the project name as needed, so when communicating with the Pulumi Service we
// always use the name the service expects. (So that a similar, but not technically valid
// name may be put in Pulumi.yaml without causing problems.)
if filter.Project != nil {
cleanedProj := cleanProjectName(*filter.Project)
filter.Project = &cleanedProj
}
// Duplicate type to avoid circular dependency.
clientFilter := client.ListStacksFilter{
Organization: filter.Organization,
Project: filter.Project,
TagName: filter.TagName,
TagValue: filter.TagValue,
}
apiSummaries, outContToken, err := b.client.ListStacks(ctx, clientFilter, inContToken)
if err != nil {
return nil, nil, err
}
// Convert []apitype.StackSummary into []backend.StackSummary.
backendSummaries := slice.Prealloc[backend.StackSummary](len(apiSummaries))
for _, apiSummary := range apiSummaries {
backendSummary := cloudStackSummary{
summary: apiSummary,
b: b,
}
backendSummaries = append(backendSummaries, backendSummary)
}
return backendSummaries, outContToken, nil
}
func (b *cloudBackend) RemoveStack(ctx context.Context, stack backend.Stack, force bool) (bool, error) {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
return false, err
}
return b.client.DeleteStack(ctx, stackID, force)
}
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
func (b *cloudBackend) RenameStack(ctx context.Context, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
newName tokens.QName,
) (backend.StackReference, error) {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
return nil, err
}
// Support a qualified stack name, which would also rename the stack's project too.
// e.g. if you want to change the project name on the Pulumi Console to reflect a
// new value in Pulumi.yaml.
newRef, err := b.ParseStackReference(string(newName))
if err != nil {
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
return nil, err
}
newIdentity, err := b.getCloudStackIdentifier(newRef)
if err != nil {
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
return nil, err
}
if stackID.Owner != newIdentity.Owner {
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
errMsg := fmt.Sprintf(
"New stack owner, %s, does not match existing owner, %s.\n\n",
stackID.Owner, newIdentity.Owner)
// Re-parse the name using the parseStackName function to avoid the logic in ParseStackReference
// that auto-populates the owner property with the currently logged in account. We actually want to
// give a different error message if the raw stack name itself didn't include an owner part.
parsedName, err := b.parseStackName(string(newName))
contract.IgnoreError(err)
if parsedName.Owner == "" {
errMsg += fmt.Sprintf(
" Did you forget to include the owner name? If yes, rerun the command as follows:\n\n"+
" $ pulumi stack rename %s/%s\n\n",
stackID.Owner, newName)
}
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
errMsgSuffix := "."
if consoleURL, err := b.StackConsoleURL(stack.Ref()); err == nil {
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
errMsgSuffix = ":\n\n " + consoleURL + "/settings/options"
}
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
errMsg += " You cannot transfer stack ownership via a rename. If you wish to transfer ownership\n" +
" of a stack to another organization, you can do so in the Pulumi Console by going to the\n" +
" \"Settings\" page of the stack and then clicking the \"Transfer Stack\" button"
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
return nil, errors.New(errMsg + errMsgSuffix)
}
Correctly rename stack files during a rename (#5812) * Correctly rename stack files during a rename This fixes pulumi/pulumi#4463, by renaming a stack's configuration file based on its stack-part, and ignoring the owner-part. Our workspace system doesn't recognize configuration files with fully qualified names. That, by the way, causes problems if we have multiple stacks in different organizations that share a stack-part. The fix here is simple: propagate the new StackReference from the Rename operation and rely on the backend's normalization to a simple name, and then use that the same way we are using a StackReference to determine the path for the origin stack. An alternative fix is to recognize fully qualified config files, however, there's a fair bit of cleanup we will be doing as part of https://github.com/pulumi/pulumi/issues/2522 and https://github.com/pulumi/pulumi/issues/4605, so figured it is best to make this work the way the system expects first, and revisit it as part of those overall workstreams. I also suspect we may want to consider changing the default behavior here as part of https://github.com/pulumi/pulumi/issues/5731. Tests TBD; need some advice on how best to test this since it only happens with our HTTP state backend -- all integration tests appear to use the local filestate backend at the moment. * Add a changelog entry for bug fix * Add some stack rename tests * Fix a typo * Address CR feedback * Make some logic clearer Use "parsedName" instead of "qn", add a comment explaining why we're doing this, and also explicitly ignore the error rather than implicitly doing so with _.
2020-12-02 00:55:48 +00:00
if err = b.client.RenameStack(ctx, stackID, newIdentity); err != nil {
return nil, err
}
return newRef, nil
}
func (b *cloudBackend) Preview(ctx context.Context, stack backend.Stack,
Add --import-file to pulumi preview (#14548) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/12768. This will generate an import file for every resource the preview wants to Create. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-12-05 08:32:40 +00:00
op backend.UpdateOperation, events chan<- engine.Event,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
) (*deploy.Plan, sdkDisplay.ResourceChanges, result.Result) {
// We can skip PreviewThenPromptThenExecute, and just go straight to Execute.
2018-09-21 20:57:57 +00:00
opts := backend.ApplierOptions{
DryRun: true,
ShowLink: true,
}
2018-09-08 21:19:42 +00:00
return b.apply(
Add --import-file to pulumi preview (#14548) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/12768. This will generate an import file for every resource the preview wants to Create. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-12-05 08:32:40 +00:00
ctx, apitype.PreviewUpdate, stack, op, opts, events)
Revise the way previews are controlled I found the flag --force to be a strange name for skipping a preview, since that name is usually reserved for operations that might be harmful and yet you're coercing a tool to do it anyway, knowing there's a chance you're going to shoot yourself in the foot. I also found that what I almost always want in the situation where --force was being used is to actually just run a preview and have the confirmation auto-accepted. Going straight to --force isn't the right thing in a CI scenario, where you actually want to run a preview first, just to ensure there aren't any issues, before doing the update. In a sense, there are four options here: 1. Run a preview, ask for confirmation, then do an update (the default). 2. Run a preview, auto-accept, and then do an update (the CI scenario). 3. Just run a preview with neither a confirmation nor an update (dry run). 4. Just do an update, without performing a preview beforehand (rare). This change enables all four workflows in our CLI. Rather than have an explosion of flags, we have a single flag, --preview, which can specify the mode that we're operating in. The following are the values which correlate to the above four modes: 1. "": default (no --preview specified) 2. "auto": auto-accept preview confirmation 3. "only": only run a preview, don't confirm or update 4. "skip": skip the preview altogether As part of this change, I redid a bit of how the preview modes were specified. Rather than booleans, which had some illegal combinations, this change introduces a new enum type. Furthermore, because the engine is wholly ignorant of these flags -- and only the backend understands them -- it was confusing to me that engine.UpdateOptions stored this flag, especially given that all interesting engine options _also_ accepted a dryRun boolean. As of this change, the backend.PreviewBehavior controls the preview options.
2018-04-28 21:50:17 +00:00
}
func (b *cloudBackend) Update(ctx context.Context, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
op backend.UpdateOperation,
) (sdkDisplay.ResourceChanges, result.Result) {
return backend.PreviewThenPromptThenExecute(ctx, apitype.UpdateUpdate, stack, op, b.apply)
}
func (b *cloudBackend) Import(ctx context.Context, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
op backend.UpdateOperation, imports []deploy.Import,
) (sdkDisplay.ResourceChanges, result.Result) {
op.Imports = imports
Add preview-only flag for destroy and import (#15336) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Figured I could round out #1666 while I was in the area. Fixes #15304 Fixes #15303 Fixes #1666 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-02-02 00:29:03 +00:00
if op.Opts.PreviewOnly {
// We can skip PreviewThenPromptThenExecute, and just go straight to Execute.
opts := backend.ApplierOptions{
DryRun: true,
ShowLink: true,
}
op.Opts.Engine.GeneratePlan = false
_, changes, res := b.apply(
ctx, apitype.ResourceImportUpdate, stack, op, opts, nil /*events*/)
return changes, res
}
return backend.PreviewThenPromptThenExecute(ctx, apitype.ResourceImportUpdate, stack, op, b.apply)
}
func (b *cloudBackend) Refresh(ctx context.Context, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
op backend.UpdateOperation,
) (sdkDisplay.ResourceChanges, result.Result) {
if op.Opts.PreviewOnly {
// We can skip PreviewThenPromptThenExecute, and just go straight to Execute.
opts := backend.ApplierOptions{
DryRun: true,
ShowLink: true,
}
op.Opts.Engine.GeneratePlan = false
_, changes, res := b.apply(
ctx, apitype.RefreshUpdate, stack, op, opts, nil /*events*/)
return changes, res
}
return backend.PreviewThenPromptThenExecute(ctx, apitype.RefreshUpdate, stack, op, b.apply)
}
func (b *cloudBackend) Destroy(ctx context.Context, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
op backend.UpdateOperation,
) (sdkDisplay.ResourceChanges, result.Result) {
Add preview-only flag for destroy and import (#15336) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Figured I could round out #1666 while I was in the area. Fixes #15304 Fixes #15303 Fixes #1666 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-02-02 00:29:03 +00:00
if op.Opts.PreviewOnly {
// We can skip PreviewThenPromptThenExecute, and just go straight to Execute.
opts := backend.ApplierOptions{
DryRun: true,
ShowLink: true,
}
op.Opts.Engine.GeneratePlan = false
_, changes, res := b.apply(
ctx, apitype.DestroyUpdate, stack, op, opts, nil /*events*/)
return changes, res
}
return backend.PreviewThenPromptThenExecute(ctx, apitype.DestroyUpdate, stack, op, b.apply)
}
func (b *cloudBackend) Watch(ctx context.Context, stk backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
op backend.UpdateOperation, paths []string,
) result.Result {
return backend.Watch(ctx, b, stk, op, b.apply, paths)
}
func (b *cloudBackend) Query(ctx context.Context, op backend.QueryOperation) error {
return b.query(ctx, op, nil /*events*/)
}
Adds two new CLI features - search and AI search (#13611) Adds initial pulumi search implementation <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/13489 Fixes https://github.com/pulumi/pulumi/issues/12868 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-08-21 15:06:46 +00:00
func (b *cloudBackend) Search(
ctx context.Context, orgName string, queryParams *apitype.PulumiQueryRequest,
) (*apitype.ResourceSearchResponse, error) {
Addresses initial Org Search feedback (#13920) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Based on initial Org Search feedback, we were missing a few things in the original implementation. This adds the following: - Displays the raw query which was submitted to Pulumi for both basic org search and AI assisted search - Validates whether the org provided is the user's individual org - AI assist and search is not supported for individual orgs - Aligns `pulumi org search` syntax with that supported in the console. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-09-12 00:18:43 +00:00
results, err := b.Client().GetSearchQueryResults(ctx, orgName, queryParams, b.CloudConsoleURL())
Safeguards org search against unset default orgs (#13947) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Currently, if a user has no default org set, and no org is provided via --org, `GetBackendConfigDefaultOrg` returns nothing, which means no org is provided when querying the Pulumi Cloud service - this results in a 404, and a nil pointer error when attempting to retrieve query parameters from that API call. This falls back to the user name when no org is provided by the user or retrieved by `GetBackendConfigDefaultOrg`, as well as returning an error when one arises from the service call rather than returning the error later. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-09-13 22:09:04 +00:00
if err != nil {
return nil, err
}
Addresses initial Org Search feedback (#13920) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Based on initial Org Search feedback, we were missing a few things in the original implementation. This adds the following: - Displays the raw query which was submitted to Pulumi for both basic org search and AI assisted search - Validates whether the org provided is the user's individual org - AI assist and search is not supported for individual orgs - Aligns `pulumi org search` syntax with that supported in the console. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-09-12 00:18:43 +00:00
results.Query = queryParams.Query
Safeguards org search against unset default orgs (#13947) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Currently, if a user has no default org set, and no org is provided via --org, `GetBackendConfigDefaultOrg` returns nothing, which means no org is provided when querying the Pulumi Cloud service - this results in a 404, and a nil pointer error when attempting to retrieve query parameters from that API call. This falls back to the user name when no org is provided by the user or retrieved by `GetBackendConfigDefaultOrg`, as well as returning an error when one arises from the service call rather than returning the error later. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-09-13 22:09:04 +00:00
return results, nil
Adds two new CLI features - search and AI search (#13611) Adds initial pulumi search implementation <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/13489 Fixes https://github.com/pulumi/pulumi/issues/12868 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-08-21 15:06:46 +00:00
}
func (b *cloudBackend) NaturalLanguageSearch(
ctx context.Context, orgName string, queryString string,
) (*apitype.ResourceSearchResponse, error) {
parsedResults, err := b.Client().GetNaturalLanguageQueryResults(ctx, orgName, queryString)
if err != nil {
return nil, err
}
requestBody := apitype.PulumiQueryRequest{Query: parsedResults.Query}
[org search] Adds both the display of and the ability to open search results URLs (#13879) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Displays to users a copyable URL to view org search results in Pulumi Cloud as well as a `--web` flag to automatically open those results for them. Fixes https://github.com/pulumi/pulumi.ai/issues/207 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-09-11 16:33:56 +00:00
results, err := b.Client().GetSearchQueryResults(ctx, orgName, &requestBody, b.CloudConsoleURL())
Addresses initial Org Search feedback (#13920) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Based on initial Org Search feedback, we were missing a few things in the original implementation. This adds the following: - Displays the raw query which was submitted to Pulumi for both basic org search and AI assisted search - Validates whether the org provided is the user's individual org - AI assist and search is not supported for individual orgs - Aligns `pulumi org search` syntax with that supported in the console. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-09-12 00:18:43 +00:00
results.Query = parsedResults.Query
Adds two new CLI features - search and AI search (#13611) Adds initial pulumi search implementation <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/13489 Fixes https://github.com/pulumi/pulumi/issues/12868 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-08-21 15:06:46 +00:00
if err != nil {
return nil, err
}
return results, err
}
Adds Pulumi AI integrations with Pulumi New (#14685) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Now that we support .zip archive sources for Pulumi New, we have all of the API surface we need to provide a full Pulumi New experience using Pulumi AI. This PR introduces a few modes of interacting with Pulumi AI to generate Pulumi projects. - The default `pulumi new` experience now begins with a choice between `ai` and `template` modes - the `template` mode represents the current state of running `pulumi new`, while `ai` provides an interactive experience with Pulumi AI. - The user can iteratively ask questions to improve or change the resulting program - each time a prompt is completed, they are asked to `refine`, `no`, or `yes` their session - `refine` allows a follow-on prompt to be submitted. `no` ends the session without generating a pulumi project, and `yes` generates a Pulumi project from the most recent program returned by Pulumi AI. - Additionally, top-level flags, `--ai` and `--language` are provided to fill in default values for the AI mode. When a prompt is provided with a language, it is automatically submitted to Pulumi AI - if either is missing, the user is prompted for whichever value is missing. Fixes https://github.com/pulumi/pulumi.ai/issues/441 Fixes https://github.com/pulumi/pulumi.ai/issues/443 Fixes https://github.com/pulumi/pulumi.ai/issues/444 Depends on https://github.com/pulumi/pulumi.ai/pull/472 Depends on https://github.com/pulumi/pulumi.ai/pull/507 Depends on https://github.com/pulumi/pulumi.ai/pull/508 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-12-20 22:08:09 +00:00
func (b *cloudBackend) PromptAI(
ctx context.Context, requestBody AIPromptRequestBody,
) (*http.Response, error) {
res, err := b.client.SubmitAIPrompt(ctx, requestBody)
Fix nil pointer dereference in pulumi new --ai (#15861) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description Found by @Frassle We were dereferencing the response pointer before checking the returned error, resulting in a nil pointer dereference. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/15860 ## Checklist - [ ] I have run `make tidy` to update any new dependencies - [ ] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-04-04 15:26:09 +00:00
if err != nil {
return nil, err
}
Adds Pulumi AI integrations with Pulumi New (#14685) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Now that we support .zip archive sources for Pulumi New, we have all of the API surface we need to provide a full Pulumi New experience using Pulumi AI. This PR introduces a few modes of interacting with Pulumi AI to generate Pulumi projects. - The default `pulumi new` experience now begins with a choice between `ai` and `template` modes - the `template` mode represents the current state of running `pulumi new`, while `ai` provides an interactive experience with Pulumi AI. - The user can iteratively ask questions to improve or change the resulting program - each time a prompt is completed, they are asked to `refine`, `no`, or `yes` their session - `refine` allows a follow-on prompt to be submitted. `no` ends the session without generating a pulumi project, and `yes` generates a Pulumi project from the most recent program returned by Pulumi AI. - Additionally, top-level flags, `--ai` and `--language` are provided to fill in default values for the AI mode. When a prompt is provided with a language, it is automatically submitted to Pulumi AI - if either is missing, the user is prompted for whichever value is missing. Fixes https://github.com/pulumi/pulumi.ai/issues/441 Fixes https://github.com/pulumi/pulumi.ai/issues/443 Fixes https://github.com/pulumi/pulumi.ai/issues/444 Depends on https://github.com/pulumi/pulumi.ai/pull/472 Depends on https://github.com/pulumi/pulumi.ai/pull/507 Depends on https://github.com/pulumi/pulumi.ai/pull/508 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-12-20 22:08:09 +00:00
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to submit AI prompt: %s", res.Status)
}
Fix nil pointer dereference in pulumi new --ai (#15861) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description Found by @Frassle We were dereferencing the response pointer before checking the returned error, resulting in a nil pointer dereference. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes https://github.com/pulumi/pulumi/issues/15860 ## Checklist - [ ] I have run `make tidy` to update any new dependencies - [ ] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-04-04 15:26:09 +00:00
return res, nil
Adds Pulumi AI integrations with Pulumi New (#14685) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Now that we support .zip archive sources for Pulumi New, we have all of the API surface we need to provide a full Pulumi New experience using Pulumi AI. This PR introduces a few modes of interacting with Pulumi AI to generate Pulumi projects. - The default `pulumi new` experience now begins with a choice between `ai` and `template` modes - the `template` mode represents the current state of running `pulumi new`, while `ai` provides an interactive experience with Pulumi AI. - The user can iteratively ask questions to improve or change the resulting program - each time a prompt is completed, they are asked to `refine`, `no`, or `yes` their session - `refine` allows a follow-on prompt to be submitted. `no` ends the session without generating a pulumi project, and `yes` generates a Pulumi project from the most recent program returned by Pulumi AI. - Additionally, top-level flags, `--ai` and `--language` are provided to fill in default values for the AI mode. When a prompt is provided with a language, it is automatically submitted to Pulumi AI - if either is missing, the user is prompted for whichever value is missing. Fixes https://github.com/pulumi/pulumi.ai/issues/441 Fixes https://github.com/pulumi/pulumi.ai/issues/443 Fixes https://github.com/pulumi/pulumi.ai/issues/444 Depends on https://github.com/pulumi/pulumi.ai/pull/472 Depends on https://github.com/pulumi/pulumi.ai/pull/507 Depends on https://github.com/pulumi/pulumi.ai/pull/508 ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> --------- Co-authored-by: Aaron Friel <mayreply@aaronfriel.com>
2023-12-20 22:08:09 +00:00
}
type updateMetadata struct {
version int
leaseToken string
messages []apitype.Message
}
func (b *cloudBackend) createAndStartUpdate(
ctx context.Context, action apitype.UpdateKind, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
op *backend.UpdateOperation, dryRun bool,
) (client.UpdateIdentifier, updateMetadata, error) {
stackRef := stack.Ref()
stackID, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return client.UpdateIdentifier{}, updateMetadata{}, err
}
if currentProjectContradictsWorkspace(op.Proj, stackID) {
return client.UpdateIdentifier{}, updateMetadata{}, fmt.Errorf(
"provided project name %q doesn't match Pulumi.yaml", stackID.Project)
}
metadata := apitype.UpdateMetadata{
Message: op.M.Message,
Environment: op.M.Environment,
}
update, updateDetails, err := b.client.CreateUpdate(
ctx, action, stackID, op.Proj, op.StackConfiguration.Config, metadata, op.Opts.Engine, dryRun)
if err != nil {
return client.UpdateIdentifier{}, updateMetadata{}, err
}
//
2019-07-13 01:32:50 +00:00
// TODO[pulumi-service#3745]: Move this to the plugin-gathering routine when we have a dedicated
// service API when for getting a list of the required policies to run.
//
// For now, this list is given to us when we start an update; yet, the list of analyzers to boot
// is given to us by CLI flag, and passed to the step generator (which lazily instantiates the
// plugins) via `op.Opts.Engine.Analyzers`. Since the "start update" API request is sent well
// after this field is populated, we instead populate the `RequiredPlugins` field here.
//
// Once this API is implemented, we can safely move these lines to the plugin-gathering code,
// which is much closer to being the "correct" place for this stuff.
//
for _, policy := range updateDetails.RequiredPolicies {
op.Opts.Engine.RequiredPolicies = append(
op.Opts.Engine.RequiredPolicies, newCloudRequiredPolicy(b.client, policy, update.Owner))
}
// Start the update. We use this opportunity to pass new tags to the service, to pick up any
// metadata changes.
tags, err := backend.GetMergedStackTags(ctx, stack, op.Root, op.Proj, op.StackConfiguration.Config)
if err != nil {
return client.UpdateIdentifier{}, updateMetadata{}, fmt.Errorf("getting stack tags: %w", err)
}
version, token, err := b.client.StartUpdate(ctx, update, tags)
if err != nil {
if err, ok := err.(*apitype.ErrorResponse); ok && err.Code == 409 {
conflict := backend.ConflictingUpdateError{Err: err}
return client.UpdateIdentifier{}, updateMetadata{}, conflict
}
return client.UpdateIdentifier{}, updateMetadata{}, err
}
2018-08-03 03:13:12 +00:00
// Any non-preview update will be considered part of the stack's update history.
if action != apitype.PreviewUpdate {
logging.V(7).Infof("Stack %s being updated to version %d", stackRef, version)
}
return update, updateMetadata{
version: version,
leaseToken: token,
messages: updateDetails.Messages,
}, nil
}
// apply actually performs the provided type of update on a stack hosted in the Pulumi Cloud.
func (b *cloudBackend) apply(
ctx context.Context, kind apitype.UpdateKind, stack backend.Stack,
op backend.UpdateOperation, opts backend.ApplierOptions,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
events chan<- engine.Event,
) (*deploy.Plan, sdkDisplay.ResourceChanges, result.Result) {
2018-09-21 20:57:57 +00:00
actionLabel := backend.ActionLabel(kind, opts.DryRun)
if !(op.Opts.Display.JSONDisplay || op.Opts.Display.Type == display.DisplayWatch) {
// Print a banner so it's clear this is going to the cloud.
fmt.Printf(op.Opts.Display.Color.Colorize(
colors.SpecHeadline+"%s (%s)"+colors.Reset+"\n\n"), actionLabel, stack.Ref())
}
2018-09-21 20:57:57 +00:00
// Create an update object to persist results.
update, updateMeta, err := b.createAndStartUpdate(ctx, kind, stack, &op, opts.DryRun)
if err != nil {
Preview of update plans (#8448) * Implement resource plans in the engine * Plumb plans through the CLI. * Update wording * plan renderer * constraints * Renames * Update message * fixes for rebase breaks and diffs * WIP: outputs in plans * fix diff * fixup * Liniting and test fixing * Test and fix PropertyPath.String() * Fix colors * Fix cmdutil.PrintTable to handle non-simple strings * More tests * Readd test_plan.go * lint * Test expected deletes * Test expected delete * Test missing create * Fix test for missing creates * rm Paths() * property set shrink test * notes * More tests * Pop op before constraint check * Delete plan cmd, rename arguments to preview and up * Hide behind envvars * typo * Better constraint diffs * Adds/Deletes/Updates * Fix aliased * Check more constraints * fix test * revert stack changes * Resource sames test * Fix same resource test * Fix more tests * linting * Update pkg/cmd/pulumi/up.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Update pkg/cmd/pulumi/preview.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Auto refresh if using plans * Fix TestGetRefreshOption * Fix TestExplicitDeleteBeforeReplace * lint * More copying in tests because I do not trust myself to get mutation correct * Small preview plan test * Add TestPlannedUpdateChangedStack * Revert auto-refresh changes * Validate outputs don't change * omitempty * Add manifest to plan * Add proper Plan type * wip config work * Config and manifest serder * linting * Asset NoError * Actually check error * Fix clone * Test diag message * Start on more tests * Add String and GoString to Result I got fed up assert errors in tests that looked like: ``` Expected nil, but got: &result.simpleResult{err:(*errors.fundamental)(0xc0002fa5d0)} ``` It was very hard to work out at a glance what had gone wrong and I kept having to hook a debugger just to look at what the error was. With GoString these now print something like: ``` Expected nil, but got: &simpleResult{err: Unexpected diag message: <{%reset%}>resource violates plan: properties changed: -zed, -baz, -foo<{%reset%}> } ``` Which is much more ussful. * Add test error text * Fix reporting of unseen op errors * Fix unneeded deletes * Fix unexpected deletes * Fix up tests * Fix merge conflict * lint * Fix nil map error * Fix serialisation typo * Diff against old inputs * Diff against checked goal * Diff against empty for creates * Fix test * inputs not outputs * Seperate PlanDiff type * Add properties * Fix input diffs * Handle creates * lint * Add plan message * Clone plan for update preview * Save and serialise env vars in plans * lint * pretty print json * input output difference test * test alias * fix typo in for loop * Handle resource plans with nil goal * go mod tidy * typo * Auto use plans from up previews in experimental mode * Don't preview if we have plan * Don't run previews with plans now * fixing tests * Handle diffs and goals * Update copystructure * tests/go.sum * Revert mod changes * Add copystructure to tests/go.sum * includeUnknowns * go mod tidy * Make plans for imports * Remove unused function * Move code more locally * Handle nil in serialize * Handle empty output diffs * Add test for dropping computed values * Allow computed properties to become deletes * if out the generation of plans unless experimental mode is opt'd into * lint * typo * Revert back to plans not skipping previews, this is orthognal to --skip-preview * Trying to work out non-determinism * Remove notes.txt * Hacking with check idea * Pass checked inputs back to Check from plan file * Include resource urn in constraint error * Give much more informative errors when plans fail * lint * Update expected diag strings in tests * Remove unused code * Duplicate Diff and DeepEquals methods for plans * Add comment about check ops with failures * Fix CheckedInputs comment * OutputDiff doesn't need to be a pointer * Fix checks against computed * diffStringSets * lint * lint pkg * Use 4 space indent * Don't wrap Buffer in Writer * Mark flags hidden rather than disabled * Remove envvars from plans * Assert MarkHidden error * Add to changelog * Note plan/save-plan is experimental Co-authored-by: Pat Gavlin <pat@pulumi.com> Co-authored-by: Alex Mullans <a.mullans@pulumi.com>
2022-01-31 10:31:51 +00:00
return nil, nil, result.FromError(err)
}
// Display messages from the backend if present.
if len(updateMeta.messages) > 0 {
for _, msg := range updateMeta.messages {
m := diag.RawMessage("", msg.Message)
switch msg.Severity {
case apitype.MessageSeverityError:
cmdutil.Diag().Errorf(m)
case apitype.MessageSeverityWarning:
cmdutil.Diag().Warningf(m)
case apitype.MessageSeverityInfo:
cmdutil.Diag().Infof(m)
default:
// Fallback on Info if we don't recognize the severity.
cmdutil.Diag().Infof(m)
logging.V(7).Infof("Unknown message severity: %s", msg.Severity)
}
}
fmt.Print("\n")
}
permalink := b.getPermalink(update, updateMeta.version, opts.DryRun)
return b.runEngineAction(ctx, kind, stack.Ref(), op, update, updateMeta.leaseToken, permalink, events, opts.DryRun)
}
// getPermalink returns a link to the update in the Pulumi Console.
func (b *cloudBackend) getPermalink(update client.UpdateIdentifier, version int, preview bool) string {
base := b.cloudConsoleStackPath(update.StackIdentifier)
if !preview {
return b.CloudConsoleURL(base, "updates", strconv.Itoa(version))
}
return b.CloudConsoleURL(base, "previews", update.UpdateID)
}
// query executes a query program against the resource outputs of a stack hosted in the Pulumi
// Cloud.
func (b *cloudBackend) query(ctx context.Context, op backend.QueryOperation,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
callerEventsOpt chan<- engine.Event,
) error {
return backend.RunQuery(ctx, b, op, callerEventsOpt, b.newQuery)
}
func (b *cloudBackend) runEngineAction(
ctx context.Context, kind apitype.UpdateKind, stackRef backend.StackReference,
op backend.UpdateOperation, update client.UpdateIdentifier, token, permalink string,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
callerEventsOpt chan<- engine.Event, dryRun bool,
) (*deploy.Plan, sdkDisplay.ResourceChanges, result.Result) {
2018-09-21 20:57:57 +00:00
contract.Assertf(token != "", "persisted actions require a token")
u, err := b.newUpdate(ctx, stackRef, op, update, token)
if err != nil {
Preview of update plans (#8448) * Implement resource plans in the engine * Plumb plans through the CLI. * Update wording * plan renderer * constraints * Renames * Update message * fixes for rebase breaks and diffs * WIP: outputs in plans * fix diff * fixup * Liniting and test fixing * Test and fix PropertyPath.String() * Fix colors * Fix cmdutil.PrintTable to handle non-simple strings * More tests * Readd test_plan.go * lint * Test expected deletes * Test expected delete * Test missing create * Fix test for missing creates * rm Paths() * property set shrink test * notes * More tests * Pop op before constraint check * Delete plan cmd, rename arguments to preview and up * Hide behind envvars * typo * Better constraint diffs * Adds/Deletes/Updates * Fix aliased * Check more constraints * fix test * revert stack changes * Resource sames test * Fix same resource test * Fix more tests * linting * Update pkg/cmd/pulumi/up.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Update pkg/cmd/pulumi/preview.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Auto refresh if using plans * Fix TestGetRefreshOption * Fix TestExplicitDeleteBeforeReplace * lint * More copying in tests because I do not trust myself to get mutation correct * Small preview plan test * Add TestPlannedUpdateChangedStack * Revert auto-refresh changes * Validate outputs don't change * omitempty * Add manifest to plan * Add proper Plan type * wip config work * Config and manifest serder * linting * Asset NoError * Actually check error * Fix clone * Test diag message * Start on more tests * Add String and GoString to Result I got fed up assert errors in tests that looked like: ``` Expected nil, but got: &result.simpleResult{err:(*errors.fundamental)(0xc0002fa5d0)} ``` It was very hard to work out at a glance what had gone wrong and I kept having to hook a debugger just to look at what the error was. With GoString these now print something like: ``` Expected nil, but got: &simpleResult{err: Unexpected diag message: <{%reset%}>resource violates plan: properties changed: -zed, -baz, -foo<{%reset%}> } ``` Which is much more ussful. * Add test error text * Fix reporting of unseen op errors * Fix unneeded deletes * Fix unexpected deletes * Fix up tests * Fix merge conflict * lint * Fix nil map error * Fix serialisation typo * Diff against old inputs * Diff against checked goal * Diff against empty for creates * Fix test * inputs not outputs * Seperate PlanDiff type * Add properties * Fix input diffs * Handle creates * lint * Add plan message * Clone plan for update preview * Save and serialise env vars in plans * lint * pretty print json * input output difference test * test alias * fix typo in for loop * Handle resource plans with nil goal * go mod tidy * typo * Auto use plans from up previews in experimental mode * Don't preview if we have plan * Don't run previews with plans now * fixing tests * Handle diffs and goals * Update copystructure * tests/go.sum * Revert mod changes * Add copystructure to tests/go.sum * includeUnknowns * go mod tidy * Make plans for imports * Remove unused function * Move code more locally * Handle nil in serialize * Handle empty output diffs * Add test for dropping computed values * Allow computed properties to become deletes * if out the generation of plans unless experimental mode is opt'd into * lint * typo * Revert back to plans not skipping previews, this is orthognal to --skip-preview * Trying to work out non-determinism * Remove notes.txt * Hacking with check idea * Pass checked inputs back to Check from plan file * Include resource urn in constraint error * Give much more informative errors when plans fail * lint * Update expected diag strings in tests * Remove unused code * Duplicate Diff and DeepEquals methods for plans * Add comment about check ops with failures * Fix CheckedInputs comment * OutputDiff doesn't need to be a pointer * Fix checks against computed * diffStringSets * lint * lint pkg * Use 4 space indent * Don't wrap Buffer in Writer * Mark flags hidden rather than disabled * Remove envvars from plans * Assert MarkHidden error * Add to changelog * Note plan/save-plan is experimental Co-authored-by: Pat Gavlin <pat@pulumi.com> Co-authored-by: Alex Mullans <a.mullans@pulumi.com>
2022-01-31 10:31:51 +00:00
return nil, nil, result.FromError(err)
}
// displayEvents renders the event to the console and Pulumi service. The processor for the
// will signal all events have been proceed when a value is written to the displayDone channel.
displayEvents := make(chan engine.Event)
displayDone := make(chan bool)
go u.RecordAndDisplayEvents(
backend.ActionLabel(kind, dryRun), kind, stackRef, op, permalink,
displayEvents, displayDone, op.Opts.Display, dryRun)
// The engineEvents channel receives all events from the engine, which we then forward onto other
// channels for actual processing. (displayEvents and callerEventsOpt.)
engineEvents := make(chan engine.Event)
eventsDone := make(chan bool)
go func() {
for e := range engineEvents {
displayEvents <- e
if callerEventsOpt != nil {
callerEventsOpt <- e
}
}
close(eventsDone)
}()
// We only need a snapshot manager if we're doing an update.
var snapshotManager *backend.SnapshotManager
if kind != apitype.PreviewUpdate && !dryRun {
persister := b.newSnapshotPersister(ctx, u.update, u.tokenSource)
snapshotManager = backend.NewSnapshotManager(persister, op.SecretsManager, u.GetTarget().Snapshot)
}
// Depending on the action, kick off the relevant engine activity. Note that we don't immediately check and
// return error conditions, because we will do so below after waiting for the display channels to close.
cancellationScope := op.Scopes.NewScope(engineEvents, dryRun)
engineCtx := &engine.Context{
Cancel: cancellationScope.Context(),
Events: engineEvents,
SnapshotManager: snapshotManager,
BackendClient: httpstateBackendClient{backend: backend.NewBackendClient(b, op.SecretsProvider)},
}
if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil {
engineCtx.ParentSpan = parentSpan.Context()
}
Preview of update plans (#8448) * Implement resource plans in the engine * Plumb plans through the CLI. * Update wording * plan renderer * constraints * Renames * Update message * fixes for rebase breaks and diffs * WIP: outputs in plans * fix diff * fixup * Liniting and test fixing * Test and fix PropertyPath.String() * Fix colors * Fix cmdutil.PrintTable to handle non-simple strings * More tests * Readd test_plan.go * lint * Test expected deletes * Test expected delete * Test missing create * Fix test for missing creates * rm Paths() * property set shrink test * notes * More tests * Pop op before constraint check * Delete plan cmd, rename arguments to preview and up * Hide behind envvars * typo * Better constraint diffs * Adds/Deletes/Updates * Fix aliased * Check more constraints * fix test * revert stack changes * Resource sames test * Fix same resource test * Fix more tests * linting * Update pkg/cmd/pulumi/up.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Update pkg/cmd/pulumi/preview.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Auto refresh if using plans * Fix TestGetRefreshOption * Fix TestExplicitDeleteBeforeReplace * lint * More copying in tests because I do not trust myself to get mutation correct * Small preview plan test * Add TestPlannedUpdateChangedStack * Revert auto-refresh changes * Validate outputs don't change * omitempty * Add manifest to plan * Add proper Plan type * wip config work * Config and manifest serder * linting * Asset NoError * Actually check error * Fix clone * Test diag message * Start on more tests * Add String and GoString to Result I got fed up assert errors in tests that looked like: ``` Expected nil, but got: &result.simpleResult{err:(*errors.fundamental)(0xc0002fa5d0)} ``` It was very hard to work out at a glance what had gone wrong and I kept having to hook a debugger just to look at what the error was. With GoString these now print something like: ``` Expected nil, but got: &simpleResult{err: Unexpected diag message: <{%reset%}>resource violates plan: properties changed: -zed, -baz, -foo<{%reset%}> } ``` Which is much more ussful. * Add test error text * Fix reporting of unseen op errors * Fix unneeded deletes * Fix unexpected deletes * Fix up tests * Fix merge conflict * lint * Fix nil map error * Fix serialisation typo * Diff against old inputs * Diff against checked goal * Diff against empty for creates * Fix test * inputs not outputs * Seperate PlanDiff type * Add properties * Fix input diffs * Handle creates * lint * Add plan message * Clone plan for update preview * Save and serialise env vars in plans * lint * pretty print json * input output difference test * test alias * fix typo in for loop * Handle resource plans with nil goal * go mod tidy * typo * Auto use plans from up previews in experimental mode * Don't preview if we have plan * Don't run previews with plans now * fixing tests * Handle diffs and goals * Update copystructure * tests/go.sum * Revert mod changes * Add copystructure to tests/go.sum * includeUnknowns * go mod tidy * Make plans for imports * Remove unused function * Move code more locally * Handle nil in serialize * Handle empty output diffs * Add test for dropping computed values * Allow computed properties to become deletes * if out the generation of plans unless experimental mode is opt'd into * lint * typo * Revert back to plans not skipping previews, this is orthognal to --skip-preview * Trying to work out non-determinism * Remove notes.txt * Hacking with check idea * Pass checked inputs back to Check from plan file * Include resource urn in constraint error * Give much more informative errors when plans fail * lint * Update expected diag strings in tests * Remove unused code * Duplicate Diff and DeepEquals methods for plans * Add comment about check ops with failures * Fix CheckedInputs comment * OutputDiff doesn't need to be a pointer * Fix checks against computed * diffStringSets * lint * lint pkg * Use 4 space indent * Don't wrap Buffer in Writer * Mark flags hidden rather than disabled * Remove envvars from plans * Assert MarkHidden error * Add to changelog * Note plan/save-plan is experimental Co-authored-by: Pat Gavlin <pat@pulumi.com> Co-authored-by: Alex Mullans <a.mullans@pulumi.com>
2022-01-31 10:31:51 +00:00
var plan *deploy.Plan
var changes sdkDisplay.ResourceChanges
var updateErr error
switch kind {
case apitype.PreviewUpdate:
plan, changes, updateErr = engine.Update(u, engineCtx, op.Opts.Engine, true)
case apitype.UpdateUpdate:
plan, changes, updateErr = engine.Update(u, engineCtx, op.Opts.Engine, dryRun)
case apitype.ResourceImportUpdate:
_, changes, updateErr = engine.Import(u, engineCtx, op.Opts.Engine, op.Imports, dryRun)
case apitype.RefreshUpdate:
_, changes, updateErr = engine.Refresh(u, engineCtx, op.Opts.Engine, dryRun)
case apitype.DestroyUpdate:
_, changes, updateErr = engine.Destroy(u, engineCtx, op.Opts.Engine, dryRun)
Replace a type used by the service (#15216) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> A type that is used by the Pulumi Cloud code was removed in [#15028](https://github.com/pulumi/pulumi/pull/15028/files#diff-52b25675ac0d98614d062fc1d1c9e60759f905cf7c60a9339402a62c23cc2c55L32-L33) - this PR replaces it. Fixes # (issue) ## Checklist - [ ] I have run `make tidy` to update any new dependencies - [ ] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-01-23 19:15:29 +00:00
case apitype.StackImportUpdate, apitype.RenameUpdate:
contract.Failf("unexpected %s event", kind)
default:
contract.Failf("Unrecognized update kind: %s", kind)
}
res := result.WrapIfNonNil(updateErr)
// Wait for dependent channels to finish processing engineEvents before closing.
<-displayDone
cancellationScope.Close() // Don't take any cancellations anymore, we're shutting down.
close(engineEvents)
if snapshotManager != nil {
err = snapshotManager.Close()
// If the snapshot manager failed to close, we should return that error.
// Even though all the parts of the operation have potentially succeeded, a
// snapshotting failure is likely to rear its head on the next
// operation/invocation (e.g. an invalid snapshot that fails integrity
// checks, or a failure to write that means the snapshot is incomplete).
// Reporting now should make debugging and reporting easier.
if err != nil {
return plan, changes, result.FromError(fmt.Errorf("writing snapshot: %w", err))
}
Write out snapshot errors to the user error stream (#14016) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Currently if the engine encounters an error writing out snapshots it only logs that to the V11 log. We'd like to get to the point where the engine doesn't write out invalid snapshots in the first place, but doing this in small steps to reduce blast radius of changes to a core engine loop. This is the first step, we'll log the error to the user error stream so it's more noticeable than just being in the developer logs at -v11. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-09-22 20:20:35 +00:00
}
// Make sure that the goroutine writing to displayEvents and callerEventsOpt
// has exited before proceeding
<-eventsDone
close(displayEvents)
// Mark the update as complete.
2018-09-21 20:57:57 +00:00
status := apitype.UpdateStatusSucceeded
if res != nil {
2018-09-21 20:57:57 +00:00
status = apitype.UpdateStatusFailed
}
completeErr := u.Complete(status)
if completeErr != nil {
res = result.Merge(res, result.FromError(fmt.Errorf("failed to complete update: %w", completeErr)))
}
Preview of update plans (#8448) * Implement resource plans in the engine * Plumb plans through the CLI. * Update wording * plan renderer * constraints * Renames * Update message * fixes for rebase breaks and diffs * WIP: outputs in plans * fix diff * fixup * Liniting and test fixing * Test and fix PropertyPath.String() * Fix colors * Fix cmdutil.PrintTable to handle non-simple strings * More tests * Readd test_plan.go * lint * Test expected deletes * Test expected delete * Test missing create * Fix test for missing creates * rm Paths() * property set shrink test * notes * More tests * Pop op before constraint check * Delete plan cmd, rename arguments to preview and up * Hide behind envvars * typo * Better constraint diffs * Adds/Deletes/Updates * Fix aliased * Check more constraints * fix test * revert stack changes * Resource sames test * Fix same resource test * Fix more tests * linting * Update pkg/cmd/pulumi/up.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Update pkg/cmd/pulumi/preview.go Co-authored-by: Alex Mullans <a.mullans@pulumi.com> * Auto refresh if using plans * Fix TestGetRefreshOption * Fix TestExplicitDeleteBeforeReplace * lint * More copying in tests because I do not trust myself to get mutation correct * Small preview plan test * Add TestPlannedUpdateChangedStack * Revert auto-refresh changes * Validate outputs don't change * omitempty * Add manifest to plan * Add proper Plan type * wip config work * Config and manifest serder * linting * Asset NoError * Actually check error * Fix clone * Test diag message * Start on more tests * Add String and GoString to Result I got fed up assert errors in tests that looked like: ``` Expected nil, but got: &result.simpleResult{err:(*errors.fundamental)(0xc0002fa5d0)} ``` It was very hard to work out at a glance what had gone wrong and I kept having to hook a debugger just to look at what the error was. With GoString these now print something like: ``` Expected nil, but got: &simpleResult{err: Unexpected diag message: <{%reset%}>resource violates plan: properties changed: -zed, -baz, -foo<{%reset%}> } ``` Which is much more ussful. * Add test error text * Fix reporting of unseen op errors * Fix unneeded deletes * Fix unexpected deletes * Fix up tests * Fix merge conflict * lint * Fix nil map error * Fix serialisation typo * Diff against old inputs * Diff against checked goal * Diff against empty for creates * Fix test * inputs not outputs * Seperate PlanDiff type * Add properties * Fix input diffs * Handle creates * lint * Add plan message * Clone plan for update preview * Save and serialise env vars in plans * lint * pretty print json * input output difference test * test alias * fix typo in for loop * Handle resource plans with nil goal * go mod tidy * typo * Auto use plans from up previews in experimental mode * Don't preview if we have plan * Don't run previews with plans now * fixing tests * Handle diffs and goals * Update copystructure * tests/go.sum * Revert mod changes * Add copystructure to tests/go.sum * includeUnknowns * go mod tidy * Make plans for imports * Remove unused function * Move code more locally * Handle nil in serialize * Handle empty output diffs * Add test for dropping computed values * Allow computed properties to become deletes * if out the generation of plans unless experimental mode is opt'd into * lint * typo * Revert back to plans not skipping previews, this is orthognal to --skip-preview * Trying to work out non-determinism * Remove notes.txt * Hacking with check idea * Pass checked inputs back to Check from plan file * Include resource urn in constraint error * Give much more informative errors when plans fail * lint * Update expected diag strings in tests * Remove unused code * Duplicate Diff and DeepEquals methods for plans * Add comment about check ops with failures * Fix CheckedInputs comment * OutputDiff doesn't need to be a pointer * Fix checks against computed * diffStringSets * lint * lint pkg * Use 4 space indent * Don't wrap Buffer in Writer * Mark flags hidden rather than disabled * Remove envvars from plans * Assert MarkHidden error * Add to changelog * Note plan/save-plan is experimental Co-authored-by: Pat Gavlin <pat@pulumi.com> Co-authored-by: Alex Mullans <a.mullans@pulumi.com>
2022-01-31 10:31:51 +00:00
return plan, changes, res
}
func (b *cloudBackend) CancelCurrentUpdate(ctx context.Context, stackRef backend.StackReference) error {
stackID, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return err
}
stack, err := b.client.GetStack(ctx, stackID)
if err != nil {
return err
}
if stack.ActiveUpdate == "" {
return fmt.Errorf("stack %v has never been updated", stackRef)
}
// Compute the update identifier and attempt to cancel the update.
//
// NOTE: the update kind is not relevant; the same endpoint will work for updates of all kinds.
updateID := client.UpdateIdentifier{
StackIdentifier: stackID,
UpdateKind: apitype.UpdateUpdate,
UpdateID: stack.ActiveUpdate,
}
return b.client.CancelUpdate(ctx, updateID)
}
2021-02-08 21:13:55 +00:00
func (b *cloudBackend) GetHistory(
ctx context.Context,
stackRef backend.StackReference,
pageSize int,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
page int,
) ([]backend.UpdateInfo, error) {
stack, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return nil, err
}
updates, err := b.client.GetStackUpdates(ctx, stack, pageSize, page)
if err != nil {
return nil, fmt.Errorf("failed to get stack updates: %w", err)
}
// Convert apitype.UpdateInfo objects to the backend type.
beUpdates := slice.Prealloc[backend.UpdateInfo](len(updates))
for _, update := range updates {
// Convert types from the apitype package into their internal counterparts.
cfg, err := convertConfig(update.Config)
if err != nil {
return nil, fmt.Errorf("converting configuration: %w", err)
}
beUpdates = append(beUpdates, backend.UpdateInfo{
Version: update.Version,
Kind: update.Kind,
Message: update.Message,
Environment: update.Environment,
Config: cfg,
Result: backend.UpdateResult(update.Result),
StartTime: update.StartTime,
EndTime: update.EndTime,
ResourceChanges: convertResourceChanges(update.ResourceChanges),
})
}
return beUpdates, nil
}
func (b *cloudBackend) GetLatestConfiguration(ctx context.Context,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
stack backend.Stack,
) (config.Map, error) {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return nil, err
}
cfg, err := b.client.GetLatestConfiguration(ctx, stackID)
switch {
case err == client.ErrNoPreviousDeployment:
return nil, backend.ErrNoPreviousDeployment
case err != nil:
return nil, err
default:
return cfg, nil
}
}
// convertResourceChanges converts the apitype version of sdkDisplay.ResourceChanges into the internal version.
func convertResourceChanges(changes map[apitype.OpType]int) sdkDisplay.ResourceChanges {
b := make(sdkDisplay.ResourceChanges)
for k, v := range changes {
b[sdkDisplay.StepOp(k)] = v
}
return b
}
// convertResourceChanges converts the apitype version of config.Map into the internal version.
func convertConfig(apiConfig map[string]apitype.ConfigValue) (config.Map, error) {
c := make(config.Map)
for rawK, rawV := range apiConfig {
k, err := config.ParseKey(rawK)
if err != nil {
return nil, err
}
Support lists and maps in config (#3342) This change adds support for lists and maps in config. We now allow lists/maps (and nested structures) in `Pulumi.<stack>.yaml` (or `Pulumi.<stack>.json`; yes, we currently support that). For example: ```yaml config: proj:blah: - a - b - c proj:hello: world proj:outer: inner: value proj:servers: - port: 80 ``` While such structures could be specified in the `.yaml` file manually, we support setting values in maps/lists from the command line. As always, you can specify single values with: ```shell $ pulumi config set hello world ``` Which results in the following YAML: ```yaml proj:hello world ``` And single value secrets via: ```shell $ pulumi config set --secret token shhh ``` Which results in the following YAML: ```yaml proj:token: secure: v1:VZAhuroR69FkEPTk:isKafsoZVMWA9pQayGzbWNynww== ``` Values in a list can be set from the command line using the new `--path` flag, which indicates the config key contains a path to a property in a map or list: ```shell $ pulumi config set --path names[0] a $ pulumi config set --path names[1] b $ pulumi config set --path names[2] c ``` Which results in: ```yaml proj:names - a - b - c ``` Values can be obtained similarly: ```shell $ pulumi config get --path names[1] b ``` Or setting values in a map: ```shell $ pulumi config set --path outer.inner value ``` Which results in: ```yaml proj:outer: inner: value ``` Of course, setting values in nested structures is supported: ```shell $ pulumi config set --path servers[0].port 80 ``` Which results in: ```yaml proj:servers: - port: 80 ``` If you want to include a period in the name of a property, it can be specified as: ``` $ pulumi config set --path 'nested["foo.bar"]' baz ``` Which results in: ```yaml proj:nested: foo.bar: baz ``` Examples of valid paths: - root - root.nested - 'root["nested"]' - root.double.nest - 'root["double"].nest' - 'root["double"]["nest"]' - root.array[0] - root.array[100] - root.array[0].nested - root.array[0][1].nested - root.nested.array[0].double[1] - 'root["key with \"escaped\" quotes"]' - 'root["key with a ."]' - '["root key with \"escaped\" quotes"].nested' - '["root key with a ."][100]' Note: paths that contain quotes can be surrounded by single quotes. When setting values with `--path`, if the value is `"false"` or `"true"`, it will be saved as the boolean value, and if it is convertible to an integer, it will be saved as an integer. Secure values are supported in lists/maps as well: ```shell $ pulumi config set --path --secret tokens[0] shh ``` Will result in: ```yaml proj:tokens: - secure: v1:wpZRCe36sFg1RxwG:WzPeQrCn4n+m4Ks8ps15MxvFXg== ``` Note: maps of length 1 with a key of “secure” and string value are reserved for storing secret values. Attempting to create such a value manually will result in an error: ```shell $ pulumi config set --path parent.secure foo error: "secure" key in maps of length 1 are reserved ``` **Accessing config values from the command line with JSON** ```shell $ pulumi config --json ``` Will output: ```json { "proj:hello": { "value": "world", "secret": false, "object": false }, "proj:names": { "value": "[\"a\",\"b\",\"c\"]", "secret": false, "object": true, "objectValue": [ "a", "b", "c" ] }, "proj:nested": { "value": "{\"foo.bar\":\"baz\"}", "secret": false, "object": true, "objectValue": { "foo.bar": "baz" } }, "proj:outer": { "value": "{\"inner\":\"value\"}", "secret": false, "object": true, "objectValue": { "inner": "value" } }, "proj:servers": { "value": "[{\"port\":80}]", "secret": false, "object": true, "objectValue": [ { "port": 80 } ] }, "proj:token": { "secret": true, "object": false }, "proj:tokens": { "secret": true, "object": true } } ``` If the value is a map or list, `"object"` will be `true`. `"value"` will contain the object as serialized JSON and a new `"objectValue"` property will be available containing the value of the object. If the object contains any secret values, `"secret"` will be `true`, and just like with scalar values, the value will not be outputted unless `--show-secrets` is specified. **Accessing config values from Pulumi programs** Map/list values are available to Pulumi programs as serialized JSON, so the existing `getObject`/`requireObject`/`getSecretObject`/`requireSecretObject` functions can be used to retrieve such values, e.g.: ```typescript import * as pulumi from "@pulumi/pulumi"; interface Server { port: number; } const config = new pulumi.Config(); const names = config.requireObject<string[]>("names"); for (const n of names) { console.log(n); } const servers = config.requireObject<Server[]>("servers"); for (const s of servers) { console.log(s.port); } ```
2019-11-01 20:41:27 +00:00
if rawV.Object {
if rawV.Secret {
c[k] = config.NewSecureObjectValue(rawV.String)
} else {
c[k] = config.NewObjectValue(rawV.String)
}
} else {
Support lists and maps in config (#3342) This change adds support for lists and maps in config. We now allow lists/maps (and nested structures) in `Pulumi.<stack>.yaml` (or `Pulumi.<stack>.json`; yes, we currently support that). For example: ```yaml config: proj:blah: - a - b - c proj:hello: world proj:outer: inner: value proj:servers: - port: 80 ``` While such structures could be specified in the `.yaml` file manually, we support setting values in maps/lists from the command line. As always, you can specify single values with: ```shell $ pulumi config set hello world ``` Which results in the following YAML: ```yaml proj:hello world ``` And single value secrets via: ```shell $ pulumi config set --secret token shhh ``` Which results in the following YAML: ```yaml proj:token: secure: v1:VZAhuroR69FkEPTk:isKafsoZVMWA9pQayGzbWNynww== ``` Values in a list can be set from the command line using the new `--path` flag, which indicates the config key contains a path to a property in a map or list: ```shell $ pulumi config set --path names[0] a $ pulumi config set --path names[1] b $ pulumi config set --path names[2] c ``` Which results in: ```yaml proj:names - a - b - c ``` Values can be obtained similarly: ```shell $ pulumi config get --path names[1] b ``` Or setting values in a map: ```shell $ pulumi config set --path outer.inner value ``` Which results in: ```yaml proj:outer: inner: value ``` Of course, setting values in nested structures is supported: ```shell $ pulumi config set --path servers[0].port 80 ``` Which results in: ```yaml proj:servers: - port: 80 ``` If you want to include a period in the name of a property, it can be specified as: ``` $ pulumi config set --path 'nested["foo.bar"]' baz ``` Which results in: ```yaml proj:nested: foo.bar: baz ``` Examples of valid paths: - root - root.nested - 'root["nested"]' - root.double.nest - 'root["double"].nest' - 'root["double"]["nest"]' - root.array[0] - root.array[100] - root.array[0].nested - root.array[0][1].nested - root.nested.array[0].double[1] - 'root["key with \"escaped\" quotes"]' - 'root["key with a ."]' - '["root key with \"escaped\" quotes"].nested' - '["root key with a ."][100]' Note: paths that contain quotes can be surrounded by single quotes. When setting values with `--path`, if the value is `"false"` or `"true"`, it will be saved as the boolean value, and if it is convertible to an integer, it will be saved as an integer. Secure values are supported in lists/maps as well: ```shell $ pulumi config set --path --secret tokens[0] shh ``` Will result in: ```yaml proj:tokens: - secure: v1:wpZRCe36sFg1RxwG:WzPeQrCn4n+m4Ks8ps15MxvFXg== ``` Note: maps of length 1 with a key of “secure” and string value are reserved for storing secret values. Attempting to create such a value manually will result in an error: ```shell $ pulumi config set --path parent.secure foo error: "secure" key in maps of length 1 are reserved ``` **Accessing config values from the command line with JSON** ```shell $ pulumi config --json ``` Will output: ```json { "proj:hello": { "value": "world", "secret": false, "object": false }, "proj:names": { "value": "[\"a\",\"b\",\"c\"]", "secret": false, "object": true, "objectValue": [ "a", "b", "c" ] }, "proj:nested": { "value": "{\"foo.bar\":\"baz\"}", "secret": false, "object": true, "objectValue": { "foo.bar": "baz" } }, "proj:outer": { "value": "{\"inner\":\"value\"}", "secret": false, "object": true, "objectValue": { "inner": "value" } }, "proj:servers": { "value": "[{\"port\":80}]", "secret": false, "object": true, "objectValue": [ { "port": 80 } ] }, "proj:token": { "secret": true, "object": false }, "proj:tokens": { "secret": true, "object": true } } ``` If the value is a map or list, `"object"` will be `true`. `"value"` will contain the object as serialized JSON and a new `"objectValue"` property will be available containing the value of the object. If the object contains any secret values, `"secret"` will be `true`, and just like with scalar values, the value will not be outputted unless `--show-secrets` is specified. **Accessing config values from Pulumi programs** Map/list values are available to Pulumi programs as serialized JSON, so the existing `getObject`/`requireObject`/`getSecretObject`/`requireSecretObject` functions can be used to retrieve such values, e.g.: ```typescript import * as pulumi from "@pulumi/pulumi"; interface Server { port: number; } const config = new pulumi.Config(); const names = config.requireObject<string[]>("names"); for (const n of names) { console.log(n); } const servers = config.requireObject<Server[]>("servers"); for (const s of servers) { console.log(s.port); } ```
2019-11-01 20:41:27 +00:00
if rawV.Secret {
c[k] = config.NewSecureValue(rawV.String)
} else {
c[k] = config.NewValue(rawV.String)
}
}
}
return c, nil
}
func (b *cloudBackend) GetLogs(ctx context.Context,
secretsProvider secrets.Provider, stack backend.Stack, cfg backend.StackConfiguration,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
logQuery operations.LogQuery,
) ([]operations.LogEntry, error) {
target, targetErr := b.getTarget(ctx, secretsProvider, stack.Ref(), cfg.Config, cfg.Decrypter)
2018-08-09 02:26:51 +00:00
if targetErr != nil {
return nil, targetErr
}
return diy.GetLogsForTarget(target, logQuery)
}
// ExportDeployment exports a deployment _from_ the backend service.
// This will return the stack state that was being stored on the backend service.
func (b *cloudBackend) ExportDeployment(ctx context.Context,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
stack backend.Stack,
) (*apitype.UntypedDeployment, error) {
return b.exportDeployment(ctx, stack.Ref(), nil /* latest */)
}
func (b *cloudBackend) ExportDeploymentForVersion(
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
ctx context.Context, stack backend.Stack, version string,
) (*apitype.UntypedDeployment, error) {
// The Pulumi Console defines versions as a positive integer. Parse the provided version string and
// ensure it is valid.
//
// The first stack update version is 1, and monotonically increasing from there.
versionNumber, err := strconv.Atoi(version)
if err != nil || versionNumber <= 0 {
return nil, fmt.Errorf(
"%q is not a valid stack version. It should be a positive integer",
version)
}
return b.exportDeployment(ctx, stack.Ref(), &versionNumber)
}
// exportDeployment exports the checkpoint file for a stack, optionally getting a previous version.
func (b *cloudBackend) exportDeployment(
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
ctx context.Context, stackRef backend.StackReference, version *int,
) (*apitype.UntypedDeployment, error) {
stack, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return nil, err
}
deployment, err := b.client.ExportStackDeployment(ctx, stack, version)
if err != nil {
return nil, err
}
return &deployment, nil
}
// ImportDeployment imports a deployment _into_ the backend. At the end of this operation,
// the deployment provided will be the current state stored on the backend service.
func (b *cloudBackend) ImportDeployment(ctx context.Context, stack backend.Stack,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
deployment *apitype.UntypedDeployment,
) error {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return err
}
update, err := b.client.ImportStackDeployment(ctx, stackID, deployment)
if err != nil {
return err
}
// Wait for the import to complete, which also polls and renders event output to STDOUT.
status, err := b.waitForUpdate(
ctx, backend.ActionLabel(apitype.StackImportUpdate, false /*dryRun*/), update,
display.Options{Color: colors.Always})
if err != nil {
return fmt.Errorf("waiting for import: %w", err)
} else if status != apitype.StatusSucceeded {
return fmt.Errorf("import unsuccessful: status %v", status)
}
return nil
}
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
var projectNameCleanRegexp = regexp.MustCompile("[^a-zA-Z0-9-_.]")
2019-01-25 00:53:54 +00:00
// cleanProjectName replaces undesirable characters in project names with hyphens. At some point, these restrictions
// will be further enforced by the service, but for now we need to ensure that if we are making a rest call, we
// do this cleaning on our end.
func cleanProjectName(projectName string) string {
return projectNameCleanRegexp.ReplaceAllString(projectName, "-")
}
// getCloudStackIdentifier converts a backend.StackReference to a client.StackIdentifier for the same logical stack
func (b *cloudBackend) getCloudStackIdentifier(stackRef backend.StackReference) (client.StackIdentifier, error) {
cloudBackendStackRef, ok := stackRef.(cloudBackendReference)
if !ok {
return client.StackIdentifier{}, errors.New("bad stack reference type")
Remove the need to `pulumi init` for the local backend This change removes the need to `pulumi init` when targeting the local backend. A fair amount of the change lays the foundation that the next set of changes to stop having `pulumi init` be used for cloud stacks as well. Previously, `pulumi init` logically did two things: 1. It created the bookkeeping directory for local stacks, this was stored in `<repository-root>/.pulumi`, where `<repository-root>` was the path to what we belived the "root" of your project was. In the case of git repositories, this was the directory that contained your `.git` folder. 2. It recorded repository information in `<repository-root>/.pulumi/repository.json`. This was used by the cloud backend when computing what project to interact with on Pulumi.com The new identity model will remove the need for (2), since we only need an owner and stack name to fully qualify a stack on pulumi.com, so it's easy enough to stop creating a folder just for that. However, for the local backend, we need to continue to retain some information about stacks (e.g. checkpoints, history, etc). In addition, we need to store our workspace settings (which today just contains the selected stack) somehere. For state stored by the local backend, we change the URL scheme from `local://` to `local://<optional-root-path>`. When `<optional-root-path>` is unset, it defaults to `$HOME`. We create our `.pulumi` folder in that directory. This is important because stack names now must be unique within the backend, but we have some tests using local stacks which use fixed stack names, so each integration test really wants its own "view" of the world. For the workspace settings, we introduce a new `workspaces` directory in `~/.pulumi`. In this folder we write the workspace settings file for each project. The file name is the name of the project, combined with the SHA1 of the path of the project file on disk, to ensure that multiple pulumi programs with the same project name have different workspace settings. This does mean that moving a project's location on disk will cause the CLI to "forget" what the selected stack was, which is unfortunate, but not the end of the world. If this ends up being a big pain point, we can certianly try to play games in the future (for example, if we saw a .git folder in a parent folder, we could store data in there). With respect to compatibility, we don't attempt to migrate older files to their newer locations. For long lived stacks managed using the local backend, we can provide information on where to move things to. For all stacks (regardless of backend) we'll require the user to `pulumi stack select` their stack again, but that seems like the correct trade-off vs writing complicated upgrade code.
2018-04-16 23:15:10 +00:00
}
return client.StackIdentifier{
Owner: cloudBackendStackRef.owner,
Project: cleanProjectName(string(cloudBackendStackRef.project)),
Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
Stack: cloudBackendStackRef.name,
}, nil
}
// Client returns a client object that may be used to interact with this backend.
func (b *cloudBackend) Client() *client.Client {
return b.client
}
type DisplayEventType string
const (
UpdateEvent DisplayEventType = "UpdateEvent"
ShutdownEvent DisplayEventType = "Shutdown"
)
type displayEvent struct {
Kind DisplayEventType
Payload interface{}
}
// waitForUpdate waits for the current update of a Pulumi program to reach a terminal state. Returns the
// final state. "path" is the URL endpoint to poll for updates.
func (b *cloudBackend) waitForUpdate(ctx context.Context, actionLabel string, update client.UpdateIdentifier,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
displayOpts display.Options,
) (apitype.UpdateStatus, error) {
events, done := make(chan displayEvent), make(chan bool)
defer func() {
events <- displayEvent{Kind: ShutdownEvent, Payload: nil}
<-done
close(events)
close(done)
}()
go displayEvents(strings.ToLower(actionLabel), events, done, displayOpts)
// The UpdateEvents API returns a continuation token to only get events after the previous call.
var continuationToken *string
for {
Make the CLI's waitForUpdates more resilient to transient failure We saw an issue where a user was mid-update, and got a networking error stating `read: operation timed out`. We believe this was simply a local client error, due to a flaky network. We should be resilient to such things during updates, particularly when there's no way to "reattach" to an in-progress udpate (see pulumi/pulumi#762). This change accomplishes this by changing our retry logic in the cloud backend's waitForUpdates function. Namely: * We recognize three types of failure, and react differently: - Expected HTTP errors. For instance, the 504 Gateway Timeouts that we already retried in the face of. In these cases, we will silently retry up to 10 times. After 10 times, we begin warning the user just in case this is a persistent condition. - Unexpected HTTP errors. The CLI will quit immediately and issue an error to the user, in the usual ways. This covers Unauthorized among other things. Over time, we may find that we want to intentionally move some HTTP errors into the above. - Anything else. This covers the transient networking errors case that we have just seen. I'll admit, it's a wide net, but any instance of this error issues a warning and it's up to the user to ^C out of it. We also log the error so that we'll see it if the user shares their logs with us. * We implement backoff logic so that we retry very quickly (100ms) on the first failure, and more slowly thereafter (1.5x, up to a max of 5 seconds). This helps to avoid accidentally DoSing our service.
2017-12-23 18:15:08 +00:00
// Query for the latest update results, including log entries so we can provide active status updates.
_, results, err := retry.Until(context.Background(), retry.Acceptor{
Accept: func(try int, nextRetryTime time.Duration) (bool, interface{}, error) {
return b.tryNextUpdate(ctx, update, continuationToken, try, nextRetryTime)
},
})
if err != nil {
return apitype.StatusFailed, err
}
Make the CLI's waitForUpdates more resilient to transient failure We saw an issue where a user was mid-update, and got a networking error stating `read: operation timed out`. We believe this was simply a local client error, due to a flaky network. We should be resilient to such things during updates, particularly when there's no way to "reattach" to an in-progress udpate (see pulumi/pulumi#762). This change accomplishes this by changing our retry logic in the cloud backend's waitForUpdates function. Namely: * We recognize three types of failure, and react differently: - Expected HTTP errors. For instance, the 504 Gateway Timeouts that we already retried in the face of. In these cases, we will silently retry up to 10 times. After 10 times, we begin warning the user just in case this is a persistent condition. - Unexpected HTTP errors. The CLI will quit immediately and issue an error to the user, in the usual ways. This covers Unauthorized among other things. Over time, we may find that we want to intentionally move some HTTP errors into the above. - Anything else. This covers the transient networking errors case that we have just seen. I'll admit, it's a wide net, but any instance of this error issues a warning and it's up to the user to ^C out of it. We also log the error so that we'll see it if the user shares their logs with us. * We implement backoff logic so that we retry very quickly (100ms) on the first failure, and more slowly thereafter (1.5x, up to a max of 5 seconds). This helps to avoid accidentally DoSing our service.
2017-12-23 18:15:08 +00:00
// We got a result, print it out.
updateResults := results.(apitype.UpdateResults)
for _, event := range updateResults.Events {
events <- displayEvent{Kind: UpdateEvent, Payload: event}
}
continuationToken = updateResults.ContinuationToken
// A nil continuation token means there are no more events to read and the update has finished.
if continuationToken == nil {
2018-01-11 20:05:08 +00:00
return updateResults.Status, nil
}
}
}
func displayEvents(action string, events <-chan displayEvent, done chan<- bool, opts display.Options) {
prefix := fmt.Sprintf("%s%s...", cmdutil.EmojiOr("✨ ", "@ "), action)
spinner, ticker := cmdutil.NewSpinnerAndTicker(prefix, nil, opts.Color, 8 /*timesPerSecond*/, opts.SuppressProgress)
defer func() {
spinner.Reset()
ticker.Stop()
done <- true
}()
for {
select {
case <-ticker.C:
spinner.Tick()
case event := <-events:
if event.Kind == ShutdownEvent {
return
}
// Pluck out the string.
payload := event.Payload.(apitype.UpdateEvent)
if raw, ok := payload.Fields["text"]; ok && raw != nil {
if text, ok := raw.(string); ok {
text = opts.Color.Colorize(text)
// Choose the stream to write to (by default stdout).
var stream io.Writer
if payload.Kind == apitype.StderrEvent {
stream = os.Stderr
} else {
stream = os.Stdout
}
if text != "" {
spinner.Reset()
fmt.Fprint(stream, text)
}
}
}
}
}
}
// tryNextUpdate tries to get the next update for a Pulumi program. This may time or error out, which results in a
// false returned in the first return value. If a non-nil error is returned, this operation should fail.
func (b *cloudBackend) tryNextUpdate(ctx context.Context, update client.UpdateIdentifier, continuationToken *string,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
try int, nextRetryTime time.Duration,
) (bool, interface{}, error) {
// If there is no error, we're done.
results, err := b.client.GetUpdateEvents(ctx, update, continuationToken)
if err == nil {
return true, results, nil
}
// There are three kinds of errors we might see:
// 1) Expected HTTP errors (like timeouts); silently retry.
// 2) Unexpected HTTP errors (like Unauthorized, etc); exit with an error.
// 3) Anything else; this could be any number of things, including transient errors (flaky network).
// In this case, we warn the user and keep retrying; they can ^C if it's not transient.
warn := true
if errResp, ok := err.(*apitype.ErrorResponse); ok {
if errResp.Code == 504 {
// If our request to the Pulumi Service returned a 504 (Gateway Timeout), ignore it and keep
// continuing. The sole exception is if we've done this 10 times. At that point, we will have
// been waiting for many seconds, and want to let the user know something might be wrong.
if try < 10 {
warn = false
}
logging.V(3).Infof("Expected %s HTTP %d error after %d retries (retrying): %v",
b.CloudURL(), errResp.Code, try, err)
} else {
// Otherwise, we will issue an error.
logging.V(3).Infof("Unexpected %s HTTP %d error after %d retries (erroring): %v",
b.CloudURL(), errResp.Code, try, err)
return false, nil, err
}
} else {
logging.V(3).Infof("Unexpected %s error after %d retries (retrying): %v", b.CloudURL(), try, err)
}
// Issue a warning if appropriate.
if warn {
b.d.Warningf(diag.Message("" /*urn*/, "error querying update status: %v"), err)
b.d.Warningf(diag.Message("" /*urn*/, "retrying in %vs... ^C to stop (this will not cancel the update)"),
nextRetryTime.Seconds())
}
return false, nil, nil
}
// IsValidAccessToken tries to use the provided Pulumi access token and returns if it is accepted
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
// or not. Returns error on any unexpected error.
func IsValidAccessToken(ctx context.Context, cloudURL string,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
insecure bool, accessToken string,
) (bool, string, []string, *workspace.TokenInformation, error) {
// Make a request to get the authenticated user. If it returns a successful response,
// we know the access token is legit. We also parse the response as JSON and confirm
// it has a githubLogin field that is non-empty (like the Pulumi Service would return).
username, organizations, tokenInfo, err := client.NewClient(cloudURL, accessToken,
insecure, cmdutil.Diag()).GetPulumiAccountDetails(ctx)
if err != nil {
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
if errResp, ok := err.(*apitype.ErrorResponse); ok && errResp.Code == 401 {
return false, "", nil, nil, nil
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
return false, "", nil, nil, fmt.Errorf("getting user info from %v: %w", cloudURL, err)
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
return true, username, organizations, tokenInfo, nil
Improve the overall cloud CLI experience This improves the overall cloud CLI experience workflow. Now whether a stack is local or cloud is inherent to the stack itself. If you interact with a cloud stack, we transparently talk to the cloud; if you interact with a local stack, we just do the right thing, and perform all operations locally. Aside from sometimes seeing a cloud emoji pop-up ☁️, the experience is quite similar. For example, to initialize a new cloud stack, simply: $ pulumi login Logging into Pulumi Cloud: https://pulumi.com/ Enter Pulumi access token: <enter your token> $ pulumi stack init my-cloud-stack Note that you may log into a specific cloud if you'd like. For now, this is just for our own testing purposes, but someday when we support custom clouds (e.g., Enterprise), you can just say: $ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873 The cloud is now the default. If you instead prefer a "fire and forget" style of stack, you can skip the login and pass `--local`: $ pulumi stack init my-faf-stack --local If you are logged in and run `pulumi`, we tell you as much: $ pulumi Usage: pulumi [command] // as before... Currently logged into the Pulumi Cloud ☁️ https://pulumi.com/ And if you list your stacks, we tell you which one is local or not: $ pulumi stack ls NAME LAST UPDATE RESOURCE COUNT CLOUD URL my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/ my-faf-stack n/a 0 n/a And `pulumi stack` by itself prints information like your cloud org, PPC name, and so on, in addition to the usuals. I shall write up more details and make sure to document these changes. This change also fairly significantly refactors the layout of cloud versus local logic, so that the cmd/ package is resonsible for CLI things, and the new pkg/backend/ package is responsible for the backends. The following is the overall resulting package architecture: * The backend.Backend interface can be implemented to substitute a new backend. This has operations to get and list stacks, perform updates, and so on. * The backend.Stack struct is a wrapper around a stack that has or is being manipulated by a Backend. It resembles our existing Stack notions in the engine, but carries additional metadata about its source. Notably, it offers functions that allow operations like updating and deleting on the Backend from which it came. * There is very little else in the pkg/backend/ package. * A new package, pkg/backend/local/, encapsulates all local state management for "fire and forget" scenarios. It simply implements the above logic and contains anything specific to the local experience. * A peer package, pkg/backend/cloud/, encapsulates all logic required for the cloud experience. This includes its subpackage apitype/ which contains JSON schema descriptions required for REST calls against the cloud backend. It also contains handy functions to list which clouds we have authenticated with. * A subpackage here, pkg/backend/state/, is not a provider at all. Instead, it contains all of the state management functions that are currently shared between local and cloud backends. This includes configuration logic -- including encryption -- as well as logic pertaining to which stacks are known to the workspace. This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 15:29:46 +00:00
}
// UpdateStackTags updates the stacks's tags, replacing all existing tags.
func (b *cloudBackend) UpdateStackTags(ctx context.Context,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
stack backend.Stack, tags map[apitype.StackTagName]string,
) error {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return err
}
return b.client.UpdateStackTags(ctx, stackID, tags)
}
func (b *cloudBackend) EncryptStackDeploymentSettingsSecret(ctx context.Context,
stack backend.Stack, secret string,
) (*apitype.SecretValue, error) {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return nil, err
}
return b.client.EncryptStackDeploymentSettingsSecret(ctx, stackID, secret)
}
func (b *cloudBackend) UpdateStackDeploymentSettings(ctx context.Context, stack backend.Stack,
deployment apitype.DeploymentSettings,
) error {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return err
}
return b.client.UpdateStackDeploymentSettings(ctx, stackID, deployment)
}
func (b *cloudBackend) DestroyStackDeploymentSettings(ctx context.Context, stack backend.Stack) error {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return err
}
return b.client.DestroyStackDeploymentSettings(ctx, stackID)
}
func (b *cloudBackend) GetStackDeploymentSettings(ctx context.Context,
stack backend.Stack,
) (*apitype.DeploymentSettings, error) {
stackID, err := b.getCloudStackIdentifier(stack.Ref())
if err != nil {
return nil, err
}
return b.client.GetStackDeploymentSettings(ctx, stackID)
}
const pulumiOperationHeader = "Pulumi operation"
func (b *cloudBackend) RunDeployment(ctx context.Context, stackRef backend.StackReference,
req apitype.CreateDeploymentRequest, opts display.Options, deploymentInitiator string,
suppressStreamLogs bool,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
) error {
stackID, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return err
}
resp, err := b.client.CreateDeployment(ctx, stackID, req, deploymentInitiator)
if err != nil {
return err
}
id := resp.ID
fmt.Print(opts.Color.Colorize(colors.SpecHeadline + "Preparing deployment..." + colors.Reset + "\n\n"))
if !opts.SuppressPermalink && !opts.JSONDisplay && resp.ConsoleURL != "" {
fmt.Printf(opts.Color.Colorize(
colors.SpecHeadline+"View Live: "+
colors.Underline+colors.BrightBlue+"%s"+colors.Reset+"\n"), resp.ConsoleURL)
}
if suppressStreamLogs {
return nil
}
token := ""
for {
logs, err := b.client.GetDeploymentLogs(ctx, stackID, id, token)
if err != nil {
return err
}
for _, l := range logs.Lines {
if l.Header != "" {
fmt.Print(opts.Color.Colorize(
"\n" + colors.SpecHeadline + l.Header + ":" + colors.Reset + "\n"))
// If we see it's a Pulumi operation, rather than outputting the deployment logs,
// find the associated update and show the normal rendering of the operation's events.
if l.Header == pulumiOperationHeader {
fmt.Println()
return b.showDeploymentEvents(ctx, stackID, apitype.UpdateKind(req.Operation.Operation), id, opts)
}
} else {
fmt.Print(l.Line)
}
}
// If there are no more logs for the deployment and the deployment has finished or we're not following,
// then we're done.
if logs.NextToken == "" {
break
}
// Otherwise, update the token, sleep, and loop around.
if logs.NextToken == token {
time.Sleep(500 * time.Millisecond)
}
token = logs.NextToken
}
return nil
}
func (b *cloudBackend) showDeploymentEvents(ctx context.Context, stackID client.StackIdentifier,
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
kind apitype.UpdateKind, deploymentID string, opts display.Options,
) error {
getUpdateID := func() (string, int, error) {
for tries := 0; tries < 10; tries++ {
updates, err := b.client.GetDeploymentUpdates(ctx, stackID, deploymentID)
if err != nil {
return "", 0, err
}
if len(updates) > 0 {
return updates[0].UpdateID, updates[0].Version, nil
}
time.Sleep(500 * time.Millisecond)
}
return "", 0, fmt.Errorf("could not find update associated with deployment %s", deploymentID)
}
updateID, version, err := getUpdateID()
if err != nil {
return err
}
dryRun := kind == apitype.PreviewUpdate
update := client.UpdateIdentifier{
StackIdentifier: stackID,
UpdateKind: kind,
UpdateID: updateID,
}
events := make(chan engine.Event) // Note: unbuffered, but we assume it won't matter in practice.
done := make(chan bool)
// Timings do not display correctly when rendering remote events, so suppress showing them.
opts.SuppressTimings = true
permalink := b.getPermalink(update, version, dryRun)
go display.ShowEvents(
Add tokens.StackName (#14487) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This adds a new type `tokens.StackName` which is a relatively strongly typed container for a stack name. The only weakly typed aspect of it is Go will always allow the "zero" value to be created for a struct, which for a stack name is the empty string which is invalid. To prevent introducing unexpected empty strings when working with stack names the `String()` method will panic for zero initialized stack names. Apart from the zero value, all other instances of `StackName` are via `ParseStackName` which returns a descriptive error if the string is not valid. This PR only updates "pkg/" to use this type. There are a number of places in "sdk/" which could do with this type as well, but there's no harm in doing a staggered roll out, and some parts of "sdk/" are user facing and will probably have to stay on the current `tokens.Name` and `tokens.QName` types. There are two places in the system where we panic on invalid stack names, both in the http backend. This _should_ be fine as we've had long standing validation that stacks created in the service are valid stack names. Just in case people have managed to introduce invalid stack names, there is the `PULUMI_DISABLE_VALIDATION` environment variable which will turn off the validation _and_ panicing for stack names. Users can use that to temporarily disable the validation and continue working, but it should only be seen as a temporary measure. If they have invalid names they should rename them, or if they think they should be valid raise an issue with us to change the validation code. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2023-11-15 07:44:54 +00:00
backend.ActionLabel(kind, dryRun), kind, stackID.Stack, tokens.PackageName(stackID.Project),
permalink, events, done, opts, dryRun)
// The UpdateEvents API returns a continuation token to only get events after the previous call.
var continuationToken *string
var lastEvent engine.Event
for {
resp, err := b.client.GetUpdateEngineEvents(ctx, update, continuationToken)
if err != nil {
return err
}
for _, jsonEvent := range resp.Events {
event, err := display.ConvertJSONEvent(jsonEvent)
if err != nil {
return err
}
lastEvent = event
events <- event
}
continuationToken = resp.ContinuationToken
// A nil continuation token means there are no more events to read and the update has finished.
if continuationToken == nil {
// If the event stream does not terminate with a cancel event, synthesize one here.
if lastEvent.Type != engine.CancelEvent {
events <- engine.NewCancelEvent()
}
close(events)
<-done
return nil
}
time.Sleep(500 * time.Millisecond)
}
}
type httpstateBackendClient struct {
backend deploy.BackendClient
}
func (c httpstateBackendClient) GetStackOutputs(ctx context.Context, name string) (resource.PropertyMap, error) {
// When using the cloud backend, require that stack references are fully qualified so they
// look like "<org>/<project>/<stack>"
if strings.Count(name, "/") != 2 {
Change the link to Stack References docs (#15999) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description Replace the link that we print to point to stack references docs. The old link is for `pulumi.io` that isn't used anywhere else, and also I think it goes to a wrong page and non-existing anchor. [The page](https://github.com/pulumi/pulumi-hugo/blob/master/themes/default/content/docs/using-pulumi/stack-outputs-and-references/index.md?plain=1) doesn't seem to have a short link defined. ## Checklist - [ ] I have run `make tidy` to update any new dependencies - [ ] I have run `make lint` to verify my code passes the lint check - [ ] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
2024-04-19 14:23:13 +00:00
return nil, errors.New("a stack reference's name should be of the form '<organization>/<project>/<stack>'. " +
"See https://www.pulumi.com/docs/using-pulumi/stack-outputs-and-references/#using-stack-references " +
"for more information.")
}
return c.backend.GetStackOutputs(ctx, name)
}
func (c httpstateBackendClient) GetStackResourceOutputs(
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
ctx context.Context, name string,
) (resource.PropertyMap, error) {
return c.backend.GetStackResourceOutputs(ctx, name)
}
// Represents feature-detected capabilities of the service the backend is connected to.
type capabilities struct {
// If non-nil, indicates that delta checkpoint updates are supported.
2022-12-22 22:08:46 +00:00
deltaCheckpointUpdates *apitype.DeltaCheckpointUploadsConfigV2
}
// Builds a lazy wrapper around doDetectCapabilities.
func detectCapabilities(d diag.Sink, client *client.Client) func(ctx context.Context) capabilities {
var once sync.Once
var caps capabilities
done := make(chan struct{})
get := func(ctx context.Context) capabilities {
once.Do(func() {
caps = doDetectCapabilities(ctx, d, client)
close(done)
})
<-done
return caps
}
return get
}
func doDetectCapabilities(ctx context.Context, d diag.Sink, client *client.Client) capabilities {
resp, err := client.GetCapabilities(ctx)
if err != nil {
d.Warningf(diag.Message("" /*urn*/, "failed to get capabilities: %v"), err)
return capabilities{}
}
caps, err := decodeCapabilities(resp.Capabilities)
if err != nil {
d.Warningf(diag.Message("" /*urn*/, "failed to decode capabilities: %v"), err)
return capabilities{}
}
// Allow users to opt out of deltaCheckpointUpdates even if the backend indicates it should be used. This
// remains necessary while PULUMI_OPTIMIZED_CHECKPOINT_PATCH has higher memory requirements on the client and
// may cause out-of-memory issues in constrained environments.
switch strings.ToLower(os.Getenv("PULUMI_OPTIMIZED_CHECKPOINT_PATCH")) {
case "0", "false":
caps.deltaCheckpointUpdates = nil
}
return caps
}
func decodeCapabilities(wireLevel []apitype.APICapabilityConfig) (capabilities, error) {
var parsed capabilities
for _, entry := range wireLevel {
switch entry.Capability {
2022-12-22 23:56:23 +00:00
case apitype.DeltaCheckpointUploads:
all: Fix revive issues Fixes the following issues found by revive included in the latest release of golangci-lint. Full list of issues: **pkg** ``` backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive) backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive) codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive) codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive) resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive) resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive) ``` **sdk** ``` go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive) go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive) go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive) nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive) ``` **tests** ``` integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) ```
2023-03-20 23:48:02 +00:00
var upcfg apitype.DeltaCheckpointUploadsConfigV1
if err := json.Unmarshal(entry.Configuration, &upcfg); err != nil {
2022-12-22 23:56:23 +00:00
msg := "decoding DeltaCheckpointUploadsConfig returned %w"
return capabilities{}, fmt.Errorf(msg, err)
}
parsed.deltaCheckpointUpdates = &apitype.DeltaCheckpointUploadsConfigV2{
all: Fix revive issues Fixes the following issues found by revive included in the latest release of golangci-lint. Full list of issues: **pkg** ``` backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive) backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive) codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive) codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive) resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive) resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive) ``` **sdk** ``` go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive) go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive) go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive) nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive) ``` **tests** ``` integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) ```
2023-03-20 23:48:02 +00:00
CheckpointCutoffSizeBytes: upcfg.CheckpointCutoffSizeBytes,
2022-12-22 23:56:23 +00:00
}
2022-12-22 22:08:46 +00:00
case apitype.DeltaCheckpointUploadsV2:
if entry.Version == 2 {
all: Fix revive issues Fixes the following issues found by revive included in the latest release of golangci-lint. Full list of issues: **pkg** ``` backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive) backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive) codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive) codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive) resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive) resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive) ``` **sdk** ``` go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive) go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive) go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive) nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive) ``` **tests** ``` integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) ```
2023-03-20 23:48:02 +00:00
var upcfg apitype.DeltaCheckpointUploadsConfigV2
if err := json.Unmarshal(entry.Configuration, &upcfg); err != nil {
2022-12-22 22:08:46 +00:00
msg := "decoding DeltaCheckpointUploadsConfigV2 returned %w"
return capabilities{}, fmt.Errorf(msg, err)
}
all: Fix revive issues Fixes the following issues found by revive included in the latest release of golangci-lint. Full list of issues: **pkg** ``` backend/display/object_diff.go:47:10: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) backend/display/object_diff.go:716:12: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:742:14: redefines-builtin-id: redefinition of the built-in function delete (revive) backend/display/object_diff.go:983:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (revive) backend/httpstate/backend.go:1814:4: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/backend.go:1824:5: redefines-builtin-id: redefinition of the built-in function cap (revive) backend/httpstate/client/client.go:444:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) backend/httpstate/client/client.go:455:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/org.go:113:4: if-return: redundant if ...; err != nil check, just return error instead. (revive) cmd/pulumi/util.go:216:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) codegen/docs/gen.go:428:2: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/hcl2/model/expression.go:2151:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:151:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:329:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/hcl2/syntax/comments.go:381:5: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/nodejs/gen.go:1367:5: redefines-builtin-id: redefinition of the built-in function copy (revive) codegen/python/gen_program_expressions.go:136:2: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/python/gen_program_expressions.go:142:3: redefines-builtin-id: redefinition of the built-in function close (revive) codegen/report/report.go:126:6: redefines-builtin-id: redefinition of the built-in function panic (revive) codegen/schema/docs_test.go:210:10: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) codegen/schema/schema.go:790:2: redefines-builtin-id: redefinition of the built-in type any (revive) codegen/schema/schema.go:793:4: redefines-builtin-id: redefinition of the built-in type any (revive) resource/deploy/plan.go:506:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) resource/deploy/snapshot_test.go:59:3: redefines-builtin-id: redefinition of the built-in function copy (revive) resource/deploy/state_builder.go:108:2: redefines-builtin-id: redefinition of the built-in function copy (revive) ``` **sdk** ``` go/common/resource/plugin/context.go:142:2: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/resource/plugin/plugin.go:142:12: superfluous-else: if block ends with a break statement, so drop this else and outdent its block (revive) go/common/resource/properties_diff.go:114:2: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:117:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:122:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:127:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/resource/properties_diff.go:132:4: redefines-builtin-id: redefinition of the built-in function len (revive) go/common/util/deepcopy/copy.go:30:1: redefines-builtin-id: redefinition of the built-in function copy (revive) go/common/workspace/creds.go:242:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:569:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi-language-go/main.go:706:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) go/pulumi/run_test.go:925:2: redefines-builtin-id: redefinition of the built-in type any (revive) go/pulumi/run_test.go:933:3: redefines-builtin-id: redefinition of the built-in type any (revive) nodejs/cmd/pulumi-language-nodejs/main.go:778:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:1011:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/cmd/pulumi-language-python/main.go:863:2: if-return: redundant if ...; err != nil check, just return error instead. (revive) python/python.go:230:2: redefines-builtin-id: redefinition of the built-in function print (revive) ``` **tests** ``` integration/integration_util_test.go:282:11: superfluous-else: if block ends with a continue statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) ```
2023-03-20 23:48:02 +00:00
parsed.deltaCheckpointUpdates = &upcfg
}
default:
continue
}
}
return parsed, nil
}