Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add examples package and document supported consumption patterns in README #189

Merged
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,27 @@ curl -fsSL https://raw.githubusercontent.com/Azure/draft/main/scripts/install.sh

* Windows isn't currently supported (you can use WSL)


## Draft as a Dependency

If you are looking to leverage Draft's file generation capabilities and templating within another project instead of using the CLI, you have two options: importing the Draft go packages, and wrapping the binary

### Importing Draft Go Packages
This option will provide the cleanest integration, as it directly builds Draft into your project. However, it requires that your project is written in Go.

Dockerfiles can be generated following the example in `examples/dockerfile.go`

Deployment files can be generated following the example in `examples/deployment.go`

### Wrapping the Binary
For projects written in languages other than Go, or for projects that prefer to not import the packages directly, you can wrap the Draft binary.

Several features have been implemented to make consuming draft as easy as possible:
- `draft info` prints supported language and field information in json format for easy parsing
- `--dry-run` and `--dry-run-file` flags can be used on the `create` command to generate a summary of the files that would be written to disk, and the variables that would be used in the templates
- `draft update` accepts takes a repeatable `--variable` flag that can be used to set template variables
- `draft create` takes a `--create-config` flag that can be used to input variables through a yaml file instead of interactively

## Contributing

Draft is fully compatible with [Azure Kubernetes Service](https://docs.microsoft.com/azure/aks/draft). We strongly encourage contributions to make Draft available to other cloud providers 😊!
Expand Down
65 changes: 65 additions & 0 deletions example/deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package example

import (
"fmt"

"github.com/Azure/draft/pkg/deployments"
"github.com/Azure/draft/pkg/templatewriter"
"github.com/Azure/draft/pkg/templatewriter/writers"
"github.com/Azure/draft/template"
)

// WriteDeploymentFiles generates Deployment Files using Draft, writing to a Draft TemplateWriter. See the corresponding draft.yaml file for the template inputs.
davidgamero marked this conversation as resolved.
Show resolved Hide resolved
func WriteDeploymentFiles(w templatewriter.TemplateWriter, deploymentOutputPath string, deploymentInputs map[string]string, deploymentType string) error {
d := deployments.CreateDeploymentsFromEmbedFS(template.Deployments, deploymentOutputPath)

err := d.CopyDeploymentFiles(deploymentType, deploymentInputs, w)
if err != nil {
return fmt.Errorf("failed to generate manifest: %e", err)
}
return nil
}

// WriteDeploymentFilesExample shows how to set up a fileWriter and generate a fileMap using WriteDeploymentFiles
func WriteDeploymentFilesExample() error {
// Create a file map
fileMap := make(map[string][]byte)

// Create a template writer that writes to the file map
w := writers.FileMapWriter{
FileMap: fileMap,
}

// Select the deployment type to generate the files for (must correspond to a directory in the template/deployments directory)
deploymentType := "manifests"

// Create a map of inputs to the template (must correspond to the inputs in the template/deployments/<deploymentType>/draft.yaml file)
deploymentInputs := map[string]string{
"PORT": "8080",
"APPNAME": "example-app",
"SERVICEPORT": "8080",
"NAMESPACE": "example-namespace",
"IMAGENAME": "example-image",
"IMAGETAG": "latest",
}

// Set the output path for the deployment files
outputPath := "./"

// Write the deployment files
err := WriteDeploymentFiles(&w, outputPath, deploymentInputs, deploymentType)
if err != nil {
return err
}

// Read written files from the file map
fmt.Printf("Files written in WriteDeploymentFilesExample:\n")
for filePath, fileContents := range fileMap {
if fileContents == nil {
return fmt.Errorf("file contents for %s is nil", filePath)
}
fmt.Printf(" %s\n", filePath) // Print the file path
}

return nil
}
64 changes: 64 additions & 0 deletions example/deployment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package example

import (
"fmt"
"testing"

"github.com/Azure/draft/pkg/templatewriter/writers"
)

func TestWriteDeploymentFiles(t *testing.T) {
filewriter := writers.FileMapWriter{}
outputPath := "test/path"

testCases := []struct {
name string
inputVariables map[string]string
deploymentType string
expectError bool
}{
{
name: "Test Valid Manifests Deployment Generation",
inputVariables: map[string]string{
"PORT": "8080",
"APPNAME": "testapp",
"SERVICEPORT": "8080",
"NAMESPACE": "testnamespace",
"IMAGENAME": "testimage",
"IMAGETAG": "latest",
},
deploymentType: "manifests",
expectError: false,
},
{
name: "Test Invalid Manifests Deployment Generation",
inputVariables: map[string]string{
"PORT": "8080",
},
deploymentType: "manifests",
expectError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := WriteDeploymentFiles(&filewriter, outputPath, tc.inputVariables, tc.deploymentType)
errored := err != nil
if err != nil {
fmt.Printf("WriteDeploymentFiles failed: %e\n", err)
}
if errored != tc.expectError {
t.Errorf("WriteDeploymentFiles failed: expected error %t, got %t", tc.expectError, errored)
t.Fail()
}
})
}
}

func TestWriteDeploymentFilesExample(t *testing.T) {
err := WriteDockerfileExample()
if err != nil {
t.Errorf("WriteDockerfileExample failed: %e", err)
t.Fail()
}
}
61 changes: 61 additions & 0 deletions example/dockerfile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package example

import (
"fmt"

"github.com/Azure/draft/pkg/languages"
"github.com/Azure/draft/pkg/templatewriter"
"github.com/Azure/draft/pkg/templatewriter/writers"
"github.com/Azure/draft/template"
)

// WriteDockerfile generates a Dockerfile and dockerignore using Draft, writing to a Draft TemplateWriter. See the corresponding draft.yaml file for the template inputs.
func WriteDockerfile(w templatewriter.TemplateWriter, dockerfileOutputPath string, dockerfileInputs map[string]string, generationLanguage string) error {
l := languages.CreateLanguagesFromEmbedFS(template.Dockerfiles, dockerfileOutputPath)

err := l.CreateDockerfileForLanguage(generationLanguage, dockerfileInputs, w)
if err != nil {
return fmt.Errorf("failed to generate dockerfile: %e", err)
}
return nil
}

// WriteDockerfileExample shows how to set up a fileWriter and generate a fileMap using WriteDockerfile
func WriteDockerfileExample() error {
// Create a file map
fileMap := make(map[string][]byte)

// Create a template writer that writes to the file map
w := writers.FileMapWriter{
FileMap: fileMap,
}

// Select the language to generate the Dockerfile for (must correspond to a directory in the template/dockerfiles directory)
generationLanguage := "go"

// Create a map of inputs to the template (must correspond to the inputs in the template/dockerfiles/<language>/draft.yaml file)
dockerfileInputs := map[string]string{
"PORT": "8080",
"VERSION": "1.20",
}

// Set the output path for the Dockerfile
outputPath := "./"

// Write the Dockerfile
err := WriteDockerfile(&w, outputPath, dockerfileInputs, generationLanguage)
if err != nil {
return err
}

// Read written files from the file map
fmt.Printf("Files written in WriteDockerfileExample:\n")
for filePath, fileContents := range fileMap {
if fileContents == nil {
return fmt.Errorf("file contents for %s is nil", filePath)
}
fmt.Printf(" %s\n", filePath) // Print the file path
}

return nil
}
69 changes: 69 additions & 0 deletions example/dockerfile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package example

import (
"fmt"
"testing"

"github.com/Azure/draft/pkg/templatewriter/writers"
)

func TestWriteDockerfile(t *testing.T) {
templateWriter := writers.FileMapWriter{}
outputPath := "test/path"

testCases := []struct {
name string
inputVariables map[string]string
generationLanguage string
expectError bool
}{

{
name: "Test Valid Go Dockerfile Generation",
inputVariables: map[string]string{
"PORT": "8080",
"VERSION": "1.20",
},
generationLanguage: "go",
expectError: false,
},
{
name: "Test Invalid Go Dockerfile Generation",
inputVariables: map[string]string{
"PORT": "8080",
},
generationLanguage: "go",
expectError: true,
},
{
name: "Test Invalid GenerationLanguage",
inputVariables: map[string]string{
"PORT": "8080",
"VERSION": "1.20",
},
generationLanguage: "invalid",
expectError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := WriteDockerfile(&templateWriter, outputPath, tc.inputVariables, tc.generationLanguage)
errored := err != nil
if err != nil {
fmt.Printf("WriteDockerfile failed: %e\n", err)
}
if errored != tc.expectError {
t.Errorf("WriteDockerfile failed: expected error %t, got %t", tc.expectError, errored)
t.Fail()
}
})
}
}

func TestWriteDockerfileExample(t *testing.T) {
err := WriteDockerfileExample()
if err != nil {
t.Errorf("WriteDockerfileExample failed: %e", err)
}
}
2 changes: 1 addition & 1 deletion pkg/linguist/data/vendor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@
- (^|/)extjs/docs/
- (^|/)extjs/builds/
- (^|/)extjs/cmd/
- (^|/)extjs/examples/
- (^|/)extjs/example/
- (^|/)extjs/locale/
- (^|/)extjs/packages/
- (^|/)extjs/plugins/
Expand Down
2 changes: 1 addition & 1 deletion pkg/linguist/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -7741,7 +7741,7 @@ xBase:
- (^|/)extjs/docs/
- (^|/)extjs/builds/
- (^|/)extjs/cmd/
- (^|/)extjs/examples/
- (^|/)extjs/example/
- (^|/)extjs/locale/
- (^|/)extjs/packages/
- (^|/)extjs/plugins/
Expand Down