Skip to content

Commit

Permalink
add samples from defang repo
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaeltm committed May 16, 2024
1 parent b64d7e5 commit 0578c7c
Show file tree
Hide file tree
Showing 546 changed files with 60,948 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/build-samples-json.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Trigger Docs Samples Rebuild

on:
push:
branches: main
paths:
- 'samples/**'

jobs:
build-json:
runs-on: ubuntu-latest
steps:
- name: Trigger CLI Autodoc
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.DOCS_ACTION_TRIGGER_TOKEN }}
repository: defang-io/defang-docs
event-type: sample-update
57 changes: 57 additions & 0 deletions .github/workflows/check-sample.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Check Samples

on:
pull_request:
paths:
- 'samples/**'

jobs:
check_samples:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Check for required files
run: |
for changed_file in $(git diff --name-only HEAD^); do
if [[ $changed_file == samples/* ]]; then
sample_dir=$(dirname $changed_file)
if [[ ! -f $sample_dir/README.md || ! -f $sample_dir/compose.yml ]]; then
echo "Missing README.md or compose.yml in $sample_dir"
exit 1
fi
fi
done
- name: Add checklist to PR description
uses: actions/github-script@v5
with:
script: |
const pr_number = context.issue.number;
const checklist = `
- [ ] I have tested that the sample runs locally
- [ ] I have tested that the sample runs in Defang Playground
- [ ] I have tested that the sample runs in BYOC
- [ ] I have documented any required config in the readme
- [ ] I have documented how to provision any third-party services in the readme
- [ ] I have documented how to run the sample in the readme (locally and with Defang)
`;
// Get the current PR
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr_number
});

// Check if the checklist already exists in the PR description
if (!pullRequest.body.includes(checklist)) {
// Update the PR description with the checklist
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr_number,
body: pullRequest.body + "\n" + checklist
});
}
33 changes: 33 additions & 0 deletions samples/golang/AWS S3/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Use an official Go runtime as a parent image
FROM golang:1.20-alpine as builder

# Set the working directory in the builder container
WORKDIR /src

# Copy go.mod and go.sum files to the workspace
COPY go.mod go.sum ./

# Download all dependencies.
RUN go mod download

# Copy the source from the current directory to the working Directory in the builder container
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the binary from builder
COPY --from=builder /src/main .

# Expose port 8080 to the world outside this container
EXPOSE 8080

# Run the binary
ENTRYPOINT ["./main"]
15 changes: 15 additions & 0 deletions samples/golang/AWS S3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

## Setup
This sample requires an API key to access AWS S3. The name of the config value is referenced in the docker-compose.yml file.
To provide a value for it, you can use the Defang CLI like this:

```
defang config set --name AWS_ACCESS_KEY
defang config set --name AWS_SECRET_KEY
```

and then enter the value when prompted.

## Testing
curl -X POST -H 'Content-Type: application/json' -d '{ "first_name" : "jane", "last_name" : "doe" }' https://xxxxxx/upload
curl https://xxxxxx/download
19 changes: 19 additions & 0 deletions samples/golang/AWS S3/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: '3.9'
services:
service1:
restart: unless-stopped
build:
context: .
dockerfile: Dockerfile
ports:
- mode: ingress
target: 8080
environment:
- AWS_ACCESS_KEY
- AWS_SECRET_KEY
deploy:
resources:
reservations:
memory: 50M
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/"]
27 changes: 27 additions & 0 deletions samples/golang/AWS S3/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module defang.io/sample

go 1.20

require (
github.com/aws/aws-sdk-go-v2/config v1.18.25
github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1
)

require (
github.com/aws/aws-sdk-go-v2 v1.18.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.24 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
)
45 changes: 45 additions & 0 deletions samples/golang/AWS S3/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY=
github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno=
github.com/aws/aws-sdk-go-v2/config v1.18.25 h1:JuYyZcnMPBiFqn87L2cRppo+rNwgah6YwD3VuyvaW6Q=
github.com/aws/aws-sdk-go-v2/config v1.18.25/go.mod h1:dZnYpD5wTW/dQF0rRNLVypB396zWCcPiBIvdvSWHEg4=
github.com/aws/aws-sdk-go-v2/credentials v1.13.24 h1:PjiYyls3QdCrzqUN35jMWtUK1vqVZ+zLfdOa/UPFDp0=
github.com/aws/aws-sdk-go-v2/credentials v1.13.24/go.mod h1:jYPYi99wUOPIFi0rhiOvXeSEReVOzBqFNOX5bXYoG2o=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25 h1:AzwRi5OKKwo4QNqPf7TjeO+tK8AyOK3GVSwmRPo7/Cs=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25/go.mod h1:SUbB4wcbSEyCvqBxv/O/IBf93RbEze7U7OnoTlpPB+g=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28 h1:vGWm5vTpMr39tEZfQeDiDAMgk+5qsnvRny3FjLpnH5w=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28/go.mod h1:spfrICMD6wCAhjhzHuy6DOZZ+LAIY10UxhUmLzpJTTs=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2 h1:NbWkRxEEIRSCqxhsHQuMiTH7yo+JZW1gp8v3elSVMTQ=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2/go.mod h1:4tfW5l4IAB32VWCDEBxCRtR9T4BWy4I4kr1spr8NgZM=
github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1 h1:O+9nAy9Bb6bJFTpeNFtd9UfHbgxO1o4ZDAM9rQp5NsY=
github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1/go.mod h1:J9kLNzEiHSeGMyN7238EjJmBpCniVzFda75Gxl/NqB8=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.10 h1:UBQjaMTCKwyUYwiVnUt6toEJwGXsLBI6al083tpjJzY=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.10/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10 h1:PkHIIJs8qvq0e5QybnZoG1K/9QTrLr9OsqCIo59jOBA=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.10/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk=
github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 h1:2DQLAKDteoEDI8zpCzqBMaZlJuoE9iTYD0gFmXVax9E=
github.com/aws/aws-sdk-go-v2/service/sts v1.19.0/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
127 changes: 127 additions & 0 deletions samples/golang/AWS S3/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package main

import (
"bytes"
"context"
"encoding/json"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"

"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
)

var (
REGION_NAME = "us-west-2"
BUCKET_NAME = "my-sample-bucket"
FILE_NAME = "file1.json"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
})

http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid method", http.StatusMethodNotAllowed)
return
}

var data map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(REGION_NAME))
if err != nil {
log.Fatalf("unable to load SDK config, %v", err)
}

client := s3.NewFromConfig(cfg)

jsonData, err := json.Marshal(data)
if err != nil {
log.Fatalf("failed to encode data to JSON, %v", err)
}

input := &s3.PutObjectInput{
Bucket: &BUCKET_NAME,
Key: &FILE_NAME,
Body: bytes.NewReader(jsonData),
}

_, err = client.PutObject(context.TODO(), input)

if err != nil {
log.Fatalf("failed to upload object, %v", err)
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
})

http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Invalid method", http.StatusMethodNotAllowed)
return
}

cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(REGION_NAME))
if err != nil {
log.Fatalf("unable to load SDK config, %v", err)
}

client := s3.NewFromConfig(cfg)

res, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
Bucket: &BUCKET_NAME,
Key: &FILE_NAME,
})

if err != nil {
var nfe *types.NoSuchKey
if errors.As(err, &nfe) {
http.Error(w, "File not found in S3 bucket", http.StatusNotFound)
} else {
// return the exact error
http.Error(w, err.Error(), http.StatusInternalServerError)
}
return
}

var fileContent map[string]interface{}
err = json.NewDecoder(res.Body).Decode(&fileContent)
if err != nil {
http.Error(w, "Failed to decode file content", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(fileContent)
})

// Register signal handler for graceful shutdown
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(sigs)

server := &http.Server{Addr: ":8080"}
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("HTTP server Serve: %v\n", err)
}
}()

sig := <-sigs
log.Printf("Received signal %v, shutting down...\n", sig)
log.Fatal(server.Shutdown(context.Background()))
}
33 changes: 33 additions & 0 deletions samples/golang/Basic Service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Use an official Go runtime as a parent image
FROM golang:1.20-alpine as builder

# Set the working directory in the builder container
WORKDIR /src

# Copy go.mod and go.sum files to the workspace
COPY go.mod go.sum ./

# Download all dependencies.
RUN go mod download

# Copy the source from the current directory to the working Directory in the builder container
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the binary from builder
COPY --from=builder /src/main .

# Expose port 8080 to the world outside this container
EXPOSE 8080

# Run the binary
ENTRYPOINT ["./main"]
3 changes: 3 additions & 0 deletions samples/golang/Basic Service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# HTTP Echo Server

A very simple example of a Go service that listens on a port and returns information about the request.
Loading

0 comments on commit 0578c7c

Please sign in to comment.