Skip to content

Commit 932b502

Browse files
committed
feat(provider): Add AWS pulumi provider
1 parent cb378e7 commit 932b502

File tree

15 files changed

+1501
-13
lines changed

15 files changed

+1501
-13
lines changed

go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ require (
2525
github.com/nitrictech/boxygen v0.0.1-rc.7.0.20211212231606-62c668408f91
2626
github.com/nitrictech/nitric v0.13.0-rc.11
2727
github.com/pkg/errors v0.9.1
28+
github.com/pulumi/pulumi-aws/sdk/v4 v4.33.0
29+
github.com/pulumi/pulumi-docker/sdk/v3 v3.1.0
30+
github.com/pulumi/pulumi/sdk/v3 v3.14.0
31+
github.com/robfig/cron/v3 v3.0.1
2832
github.com/spf13/cobra v1.2.1
2933
github.com/spf13/viper v1.9.0
34+
github.com/stretchr/testify v1.7.0
3035
github.com/valyala/fasthttp v1.32.0
3136
golang.org/x/net v0.0.0-20211105192438-b53810dc28af // indirect
3237
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect
3338
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
34-
golang.org/x/tools v0.1.8 // indirect
3539
google.golang.org/grpc v1.41.0
3640
gopkg.in/yaml.v2 v2.4.0
3741
)

go.sum

Lines changed: 88 additions & 8 deletions
Large diffs are not rendered by default.

pkg/cmd/deployment/root.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var deploymentCmd = &cobra.Command{
3636
`,
3737
}
3838

39-
var deploymentCreateCmd = &cobra.Command{
39+
var deploymentApplyCmd = &cobra.Command{
4040
Use: "apply [name]",
4141
Short: "Create or Update a new application deployment",
4242
Long: `Applies a Nitric application deployment.`,
@@ -84,9 +84,9 @@ var deploymentListCmd = &cobra.Command{
8484
}
8585

8686
func RootCommand() *cobra.Command {
87-
deploymentCmd.AddCommand(deploymentCreateCmd)
88-
target.AddOptions(deploymentCreateCmd, false)
89-
stack.AddOptions(deploymentCreateCmd)
87+
deploymentCmd.AddCommand(deploymentApplyCmd)
88+
target.AddOptions(deploymentApplyCmd, false)
89+
stack.AddOptions(deploymentApplyCmd)
9090

9191
deploymentCmd.AddCommand(deploymentDeleteCmd)
9292
target.AddOptions(deploymentDeleteCmd, false)

pkg/provider/pulumi/aws/aws.go

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
// Copyright Nitric Pty Ltd.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at:
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
package aws
18+
19+
import (
20+
"context"
21+
"io/ioutil"
22+
"os"
23+
"path"
24+
25+
"github.com/pkg/errors"
26+
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/dynamodb"
27+
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/ecr"
28+
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/s3"
29+
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/sns"
30+
"github.com/pulumi/pulumi-aws/sdk/v4/go/aws/sqs"
31+
"github.com/pulumi/pulumi/sdk/v3/go/auto"
32+
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
33+
34+
"github.com/nitrictech/newcli/pkg/provider/pulumi/types"
35+
"github.com/nitrictech/newcli/pkg/stack"
36+
"github.com/nitrictech/newcli/pkg/target"
37+
"github.com/nitrictech/newcli/pkg/utils"
38+
)
39+
40+
type awsProvider struct {
41+
s *stack.Stack
42+
t *target.Target
43+
tmpDir string
44+
}
45+
46+
func New(s *stack.Stack, t *target.Target) types.PulumiProvider {
47+
return &awsProvider{s: s, t: t}
48+
}
49+
50+
func (a *awsProvider) PluginName() string {
51+
return "aws"
52+
}
53+
54+
func (a *awsProvider) PluginVersion() string {
55+
return "v4.0.0"
56+
}
57+
58+
func (a *awsProvider) Configure(ctx context.Context, autoStack *auto.Stack) error {
59+
if a.t.Region != "" {
60+
return autoStack.SetConfig(ctx, "aws:region", auto.ConfigValue{Value: a.t.Region})
61+
}
62+
return nil
63+
}
64+
65+
func commonTags(ctx *pulumi.Context, name string) pulumi.StringMap {
66+
return pulumi.StringMap{
67+
"x-nitric-project": pulumi.String(ctx.Project()),
68+
"x-nitric-stack": pulumi.String(ctx.Stack()),
69+
"x-nitric-resource-name": pulumi.String(name),
70+
}
71+
}
72+
73+
func (a *awsProvider) Deploy(ctx *pulumi.Context) error {
74+
var err error
75+
a.tmpDir, err = ioutil.TempDir("", ctx.Stack()+"-*")
76+
if err != nil {
77+
return err
78+
}
79+
80+
topics := map[string]*sns.Topic{}
81+
for k := range a.s.Topics {
82+
topics[k], err = sns.NewTopic(ctx, k, &sns.TopicArgs{Tags: commonTags(ctx, k)})
83+
if err != nil {
84+
return errors.WithMessage(err, "sns topic "+k)
85+
}
86+
}
87+
88+
buckets := map[string]*s3.Bucket{}
89+
for k := range a.s.Buckets {
90+
buckets[k], err = s3.NewBucket(ctx, k, &s3.BucketArgs{
91+
Tags: commonTags(ctx, k),
92+
})
93+
if err != nil {
94+
return errors.WithMessage(err, "s3 bucket "+k)
95+
}
96+
}
97+
98+
queues := map[string]*sqs.Queue{}
99+
for k := range a.s.Queues {
100+
queues[k], err = sqs.NewQueue(ctx, k, &sqs.QueueArgs{
101+
Tags: commonTags(ctx, k),
102+
})
103+
if err != nil {
104+
return errors.WithMessage(err, "sqs queue "+k)
105+
}
106+
}
107+
108+
dbs := map[string]*dynamodb.Table{}
109+
for k := range a.s.Collections {
110+
dbs[k], err = dynamodb.NewTable(ctx, "mytable", &dynamodb.TableArgs{
111+
Attributes: dynamodb.TableAttributeArray{
112+
&dynamodb.TableAttributeArgs{
113+
Name: pulumi.String("_pk"),
114+
Type: pulumi.String("S"),
115+
},
116+
&dynamodb.TableAttributeArgs{
117+
Name: pulumi.String("_sk"),
118+
Type: pulumi.String("S"),
119+
},
120+
},
121+
HashKey: pulumi.String("_pk"),
122+
RangeKey: pulumi.String("_sk"),
123+
BillingMode: pulumi.String("PAY_PER_REQUEST"),
124+
Tags: commonTags(ctx, k),
125+
})
126+
if err != nil {
127+
return errors.WithMessage(err, "dynamodb table "+k)
128+
}
129+
}
130+
131+
for k, s := range a.s.Schedules {
132+
if len(topics) > 0 && s.Target.Type == "topic" && s.Target.Name != "" {
133+
err := a.schedule(ctx, k, s.Expression, topics[s.Target.Name])
134+
if err != nil {
135+
return errors.WithMessage(err, "schedule "+k)
136+
}
137+
}
138+
}
139+
140+
for k, s := range a.s.Sites {
141+
err := a.site(ctx, k, &s)
142+
if err != nil {
143+
return errors.WithMessage(err, "site "+k)
144+
}
145+
}
146+
147+
authToken, err := ecr.GetAuthorizationToken(ctx, &ecr.GetAuthorizationTokenArgs{})
148+
if err != nil {
149+
return err
150+
}
151+
152+
funcs := map[string]*Lambda{}
153+
for k, f := range a.s.Functions {
154+
image, err := newECRImage(ctx, f.Name(), &ECRImageArgs{
155+
LocalImageName: f.ImageTagName(a.s, ""),
156+
SourceImageName: f.ImageTagName(a.s, a.t.Provider),
157+
AuthToken: authToken,
158+
TempDir: a.tmpDir})
159+
if err != nil {
160+
return errors.WithMessage(err, "function image tag "+f.Name())
161+
}
162+
funcs[k], err = newLambda(ctx, k, &LambdaArgs{
163+
Topics: topics,
164+
DockerImage: image.DockerImage,
165+
Compute: &f,
166+
})
167+
if err != nil {
168+
return errors.WithMessage(err, "lambda function "+f.Name())
169+
}
170+
}
171+
172+
for k, c := range a.s.Containers {
173+
image, err := newECRImage(ctx, c.Name(), &ECRImageArgs{
174+
LocalImageName: c.ImageTagName(a.s, ""),
175+
SourceImageName: c.ImageTagName(a.s, a.t.Provider),
176+
AuthToken: authToken,
177+
TempDir: a.tmpDir})
178+
if err != nil {
179+
return errors.WithMessage(err, "function image tag "+c.Name())
180+
}
181+
funcs[k], err = newLambda(ctx, k, &LambdaArgs{
182+
Topics: topics,
183+
DockerImage: image.DockerImage,
184+
Compute: &c,
185+
})
186+
if err != nil {
187+
return errors.WithMessage(err, "lambda container "+c.Name())
188+
}
189+
}
190+
apiGateways := map[string]*ApiGateway{}
191+
for k, apiFile := range a.s.Apis {
192+
apiGateways[k], err = newApiGateway(ctx, k, &ApiGatewayArgs{
193+
ApiFilePath: path.Join(a.s.Path(), apiFile),
194+
LambdaFunctions: funcs})
195+
if err != nil {
196+
return errors.WithMessage(err, "gateway "+k)
197+
}
198+
}
199+
200+
for k, v := range a.s.EntryPoints {
201+
err = a.entrypoint(ctx, k, &v)
202+
if err != nil {
203+
return errors.WithMessage(err, "entrypoint "+k)
204+
}
205+
}
206+
207+
return nil
208+
}
209+
210+
func (a *awsProvider) CleanUp() {
211+
if a.tmpDir != "" {
212+
os.Remove(a.tmpDir)
213+
}
214+
}
215+
216+
func (a *awsProvider) site(ctx *pulumi.Context, name string, o interface{}) error {
217+
return utils.NewNotSupportedErr("site not supported on AWS yet")
218+
}
219+
220+
func (a *awsProvider) entrypoint(ctx *pulumi.Context, name string, o interface{}) error {
221+
return utils.NewNotSupportedErr("entrypoint not supported on AWS yet")
222+
}

0 commit comments

Comments
 (0)