Skip to content

Commit

Permalink
Fixing Deployment Secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
IaroslavTitov committed Jun 17, 2024
1 parent bfd8b59 commit d361a4a
Show file tree
Hide file tree
Showing 9 changed files with 1,072 additions and 78 deletions.
1 change: 1 addition & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Fixed environment tests breaking due to name collision [#296](https://github.com/pulumi/pulumi-pulumiservice/issues/296)
- Fixed import for Schedules [#270](https://github.com/pulumi/pulumi-pulumiservice/issues/270)
- Fixed noisy refresh for Team resource [#314](https://github.com/pulumi/pulumi-pulumiservice/pull/314)
- Introduced secrets in Deployment Settings, fixed refresh and import [#123](https://github.com/pulumi/pulumi-pulumiservice/issues/123)

### Miscellaneous

Expand Down
3 changes: 0 additions & 3 deletions provider/cmd/pulumi-resource-pulumiservice/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,6 @@
},
"environmentVariables": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Environment variables to set for the deployment."
},
"options": {
Expand Down
10 changes: 6 additions & 4 deletions provider/pkg/internal/pulumiapi/deployment_setting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestGetDeploymentSettings(t *testing.T) {
dsValue := DeploymentSettings{
OperationContext: &OperationContext{},
GitHub: &GitHubConfiguration{},
SourceContext: &apitype.SourceContext{},
SourceContext: &SourceContext{},
ExecutorContext: &apitype.ExecutorContext{},
}

Expand Down Expand Up @@ -74,24 +74,26 @@ func TestCreateDeploymentSettings(t *testing.T) {
dsValue := DeploymentSettings{
OperationContext: &OperationContext{},
GitHub: &GitHubConfiguration{},
SourceContext: &apitype.SourceContext{},
SourceContext: &SourceContext{},
ExecutorContext: &apitype.ExecutorContext{},
}

c, cleanup := startTestServer(t, testServerConfig{
ExpectedReqMethod: http.MethodPost,
ExpectedReqMethod: http.MethodPut,
ExpectedReqPath: "/" + path.Join("api", "stacks", orgName, projectName, stackName, "deployments", "settings"),
ResponseCode: 201,
ExpectedReqBody: dsValue,
ResponseBody: dsValue,
})
defer cleanup()

err := c.CreateDeploymentSettings(ctx, StackName{
response, err := c.CreateDeploymentSettings(ctx, StackName{
OrgName: orgName,
ProjectName: projectName,
StackName: stackName,
}, dsValue)

assert.Nil(t, err)
assert.Equal(t, dsValue, *response)
})
}
97 changes: 82 additions & 15 deletions provider/pkg/internal/pulumiapi/deployment_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pulumiapi

import (
"context"
"encoding/json"
"fmt"
"net/http"
"path"
Expand All @@ -10,25 +11,26 @@ import (
)

type DeploymentSettingsClient interface {
CreateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) error
UpdateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) error
CreateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) (*DeploymentSettings, error)
UpdateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) (*DeploymentSettings, error)
GetDeploymentSettings(ctx context.Context, stack StackName) (*DeploymentSettings, error)
DeleteDeploymentSettings(ctx context.Context, stack StackName) error
}

type DeploymentSettings struct {
OperationContext *OperationContext `json:"operationContext,omitempty"`
GitHub *GitHubConfiguration `json:"gitHub,omitempty"`
SourceContext *apitype.SourceContext `json:"sourceContext,omitempty"`
SourceContext *SourceContext `json:"sourceContext,omitempty"`
ExecutorContext *apitype.ExecutorContext `json:"executorContext,omitempty"`
AgentPoolId string `json:"agentPoolId,omitempty"`
Source *string `json:"source,omitempty"`
}

type OperationContext struct {
Options *OperationContextOptions `json:"options,omitempty"`
PreRunCommands []string `json:"PreRunCommands,omitempty"`
EnvironmentVariables map[string]apitype.SecretValue `json:"environmentVariables,omitempty"`
OIDC *OIDCConfiguration `json:"oidc,omitempty"`
Options *OperationContextOptions `json:"options,omitempty"`
PreRunCommands []string `json:"PreRunCommands,omitempty"`
EnvironmentVariables map[string]SecretValue `json:"environmentVariables,omitempty"`
OIDC *OIDCConfiguration `json:"oidc,omitempty"`
}

type OIDCConfiguration struct {
Expand Down Expand Up @@ -74,22 +76,87 @@ type GitHubConfiguration struct {
Paths []string `json:"paths,omitempty"`
}

func (c *Client) CreateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) error {
type SourceContext struct {
Git *SourceContextGit `json:"git,omitempty"`
}

type SourceContextGit struct {
RepoURL string `json:"repoURL"`
Branch string `json:"branch"`
RepoDir string `json:"repoDir,omitempty"`
Commit string `json:"commit,omitempty"`
GitAuth *GitAuthConfig `json:"gitAuth,omitempty"`
}

type GitAuthConfig struct {
PersonalAccessToken *SecretValue `json:"accessToken,omitempty"`
SSHAuth *SSHAuth `json:"sshAuth,omitempty"`
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
}

type SSHAuth struct {
SSHPrivateKey SecretValue `json:"sshPrivateKey"`
Password *SecretValue `json:"password,omitempty"`
}

type BasicAuth struct {
UserName SecretValue `json:"userName"`
Password SecretValue `json:"password"`
}

type SecretValue struct {
Value string // Plaintext if Secret is false; ciphertext otherwise.
Secret bool
}

type secretCiphertextValue struct {
Ciphertext string `json:"ciphertext"`
}

type secretWorkflowValue struct {
Secret string `json:"secret" yaml:"secret"`
}

func (v SecretValue) MarshalJSON() ([]byte, error) {
if v.Secret {
return json.Marshal(secretWorkflowValue{Secret: v.Value})
}
return json.Marshal(v.Value)
}

func (v *SecretValue) UnmarshalJSON(bytes []byte) error {
var secret secretCiphertextValue
if err := json.Unmarshal(bytes, &secret); err == nil {
v.Value, v.Secret = secret.Ciphertext, true
return nil
}

var plaintext string
if err := json.Unmarshal(bytes, &plaintext); err != nil {
return err
}
v.Value, v.Secret = plaintext, false
return nil
}

func (c *Client) CreateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) (*DeploymentSettings, error) {
apiPath := path.Join("stacks", stack.OrgName, stack.ProjectName, stack.StackName, "deployments", "settings")
_, err := c.do(ctx, http.MethodPost, apiPath, ds, nil)
var resultDS = &DeploymentSettings{}
_, err := c.do(ctx, http.MethodPut, apiPath, ds, resultDS)
if err != nil {
return fmt.Errorf("failed to create deployment settings for stack (%s): %w", stack.String(), err)
return nil, fmt.Errorf("failed to create deployment settings for stack (%s): %w", stack.String(), err)
}
return nil
return resultDS, nil
}

func (c *Client) UpdateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) error {
func (c *Client) UpdateDeploymentSettings(ctx context.Context, stack StackName, ds DeploymentSettings) (*DeploymentSettings, error) {
apiPath := path.Join("stacks", stack.OrgName, stack.ProjectName, stack.StackName, "deployments", "settings")
_, err := c.do(ctx, http.MethodPut, apiPath, ds, nil)
var resultDS = &DeploymentSettings{}
_, err := c.do(ctx, http.MethodPut, apiPath, ds, resultDS)
if err != nil {
return fmt.Errorf("failed to update deployment settings for stack (%s): %w", stack.String(), err)
return nil, fmt.Errorf("failed to update deployment settings for stack (%s): %w", stack.String(), err)
}
return nil
return resultDS, nil
}

func (c *Client) GetDeploymentSettings(ctx context.Context, stack StackName) (*DeploymentSettings, error) {
Expand Down
10 changes: 5 additions & 5 deletions provider/pkg/provider/deployment_setting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ type DeploymentSettingsClientMock struct {
getDeploymentSettingsFunc getDeploymentSettingsFunc
}

func (c *DeploymentSettingsClientMock) CreateDeploymentSettings(ctx context.Context, stack pulumiapi.StackName, ds pulumiapi.DeploymentSettings) error {
return nil
func (c *DeploymentSettingsClientMock) CreateDeploymentSettings(ctx context.Context, stack pulumiapi.StackName, ds pulumiapi.DeploymentSettings) (*pulumiapi.DeploymentSettings, error) {
return nil, nil
}
func (c *DeploymentSettingsClientMock) UpdateDeploymentSettings(ctx context.Context, stack pulumiapi.StackName, ds pulumiapi.DeploymentSettings) error {
return nil
func (c *DeploymentSettingsClientMock) UpdateDeploymentSettings(ctx context.Context, stack pulumiapi.StackName, ds pulumiapi.DeploymentSettings) (*pulumiapi.DeploymentSettings, error) {
return nil, nil
}
func (c *DeploymentSettingsClientMock) GetDeploymentSettings(ctx context.Context, stack pulumiapi.StackName) (*pulumiapi.DeploymentSettings, error) {
return c.getDeploymentSettingsFunc()
Expand Down Expand Up @@ -64,7 +64,7 @@ func TestDeploymentSettings(t *testing.T) {
return &pulumiapi.DeploymentSettings{
OperationContext: &pulumiapi.OperationContext{},
GitHub: &pulumiapi.GitHubConfiguration{},
SourceContext: &apitype.SourceContext{},
SourceContext: &pulumiapi.SourceContext{},
ExecutorContext: &apitype.ExecutorContext{},
}, nil
},
Expand Down
Loading

0 comments on commit d361a4a

Please sign in to comment.