-
-
Save ikatson/cee88cc50c52f10abdd4ea02d29cc644 to your computer and use it in GitHub Desktop.
Generate json schema for intellij terraform plugin on a community provider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
schemas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Run `./gen-custom.sh github.com/myorg/myprovider provider-name version` | |
# e.g.: `./gen-custom.sh github.com/mevansam/terraform-provider-cf cloudfoundry v1.0.0` | |
# This will place a provider-name.json directly in $HOME/.terraform.d/schemas | |
set -e | |
CUR="$(pwd)" | |
out="$CUR/schemas" | |
mkdir -p "$out" | |
rm -f "$CUR/failure.txt" | |
p="$2" | |
provider="$1/$2" | |
echo | |
echo "========================================" | |
echo "Waiting for update processes to finish" | |
go get -v "${1}" | |
echo "All providers updated" | |
echo | |
pushd "$GOPATH/src/$1" >/dev/null | |
# checkout latest tag | |
git checkout "$(git describe --tags "$(git rev-list --tags --max-count=1)")" | |
revision="$(git describe --tags)" | |
pushd "$p" >/dev/null | |
generate_one() { | |
go run generate-schema/generate-schema.go | |
if [[ $? -ne 0 ]]; then | |
echo "$1" >> "$2/failure.txt" | |
fi | |
echo "Finished $1" | |
} | |
echo "Preparing $p" | |
pwd | |
rm -rf generate-schema | |
mkdir generate-schema | |
cp -r "$CUR/template/generate-schema.go" generate-schema/generate-schema.go | |
find generate-schema -type f -exec sed -i "s@__REPO__@$provider@g" {} + | |
find generate-schema -type f -exec sed -i "s@__NAME__@$2@g" {} + | |
find generate-schema -type f -exec sed -i "s@__REVISION__@$revision@g" {} + | |
find generate-schema -type f -exec sed -i "s~__OUT__~$out~g" {} + | |
#echo "Building $p" | |
#make | |
echo "Generating schema for $p" | |
if [[ "$KILL_CPU" == "1" ]]; then | |
( | |
generate_one "$p" "$CUR" | |
)& | |
else | |
generate_one "$p" "$CUR" | |
fi | |
rm -Rf generate-schema | |
popd >/dev/null | |
if [[ "$KILL_CPU" == "1" ]]; then | |
echo | |
echo "========================================" | |
echo "Waiting for 'generate-schemas' processes to finish" | |
wait | |
echo | |
fi | |
echo "========================================" | |
echo "Everything done!" | |
echo | |
popd >/dev/null | |
mkdir -p "$HOME/.terraform.d/schemas" >/dev/null | |
cp "$CUR/schemas/$2.json" "$HOME/.terraform.d/schemas" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"github.com/hashicorp/terraform/helper/schema" | |
tf "github.com/hashicorp/terraform/terraform" | |
"__REPO__" | |
"encoding/json" | |
"fmt" | |
"os" | |
"path/filepath" | |
"reflect" | |
) | |
// ExportSchema should be called to export the structure | |
// of the provider. | |
func Export(p *schema.Provider) *ResourceProviderSchema { | |
result := new(ResourceProviderSchema) | |
result.Name = "__NAME__" | |
result.Type = "provider" | |
result.Version = "__REVISION__" | |
result.Provider = schemaMap(p.Schema).Export() | |
result.Resources = make(map[string]SchemaInfo) | |
result.DataSources = make(map[string]SchemaInfo) | |
for k, r := range p.ResourcesMap { | |
result.Resources[k] = ExportResource(r) | |
} | |
for k, ds := range p.DataSourcesMap { | |
result.DataSources[k] = ExportResource(ds) | |
} | |
return result | |
} | |
func ExportResource(r *schema.Resource) SchemaInfo { | |
return schemaMap(r.Schema).Export() | |
} | |
// schemaMap is a wrapper that adds nice functions on top of schemas. | |
type schemaMap map[string]*schema.Schema | |
// Export exports the format of this schema. | |
func (m schemaMap) Export() SchemaInfo { | |
result := make(SchemaInfo) | |
for k, v := range m { | |
item := export(v) | |
result[k] = item | |
} | |
return result | |
} | |
func export(v *schema.Schema) SchemaDefinition { | |
item := SchemaDefinition{} | |
item.Type = fmt.Sprintf("%s", v.Type) | |
item.Optional = v.Optional | |
item.Required = v.Required | |
item.Description = v.Description | |
item.InputDefault = v.InputDefault | |
item.Computed = v.Computed | |
item.MaxItems = v.MaxItems | |
item.MinItems = v.MinItems | |
item.PromoteSingle = v.PromoteSingle | |
item.ComputedWhen = v.ComputedWhen | |
item.ConflictsWith = v.ConflictsWith | |
item.Deprecated = v.Deprecated | |
item.Removed = v.Removed | |
if v.Elem != nil { | |
item.Elem = exportValue(v.Elem, fmt.Sprintf("%T", v.Elem)) | |
} | |
// TODO: Find better solution | |
if defValue, err := v.DefaultValue(); err == nil && defValue != nil && !reflect.DeepEqual(defValue, v.Default) { | |
item.Default = exportValue(defValue, fmt.Sprintf("%T", defValue)) | |
} | |
return item | |
} | |
func exportValue(value interface{}, t string) SchemaElement { | |
s2, ok := value.(*schema.Schema) | |
if ok { | |
return SchemaElement{Type: "SchemaElements", ElementsType: fmt.Sprintf("%s", s2.Type)} | |
} | |
r2, ok := value.(*schema.Resource) | |
if ok { | |
return SchemaElement{Type: "SchemaInfo", Info: ExportResource(r2)} | |
} | |
return SchemaElement{Type: t, Value: fmt.Sprintf("%v", value)} | |
} | |
func Generate(provider *schema.Provider, name string, outputPath string) { | |
outputFilePath := filepath.Join(outputPath, fmt.Sprintf("%s.json", name)) | |
if err := DoGenerate(provider, name, outputFilePath); err != nil { | |
fmt.Fprintln(os.Stderr, "Error: ", err.Error()) | |
os.Exit(255) | |
} | |
} | |
func DoGenerate(provider *schema.Provider, providerName string, outputFilePath string) error { | |
providerJson, err := json.MarshalIndent(Export(provider), "", " ") | |
if err != nil { | |
return err | |
} | |
file, err := os.Create(outputFilePath) | |
if err != nil { | |
return err | |
} | |
defer file.Close() | |
_, err = file.Write(providerJson) | |
if err != nil { | |
return err | |
} | |
return file.Sync() | |
} | |
type SchemaElement struct { | |
// One of ValueType or "SchemaElements" or "SchemaInfo" | |
Type string `json:",omitempty"` | |
// Set for simple types (from ValueType) | |
Value string `json:",omitempty"` | |
// Set if Type == "SchemaElements" | |
ElementsType string `json:",omitempty"` | |
// Set if Type == "SchemaInfo" | |
Info SchemaInfo `json:",omitempty"` | |
} | |
type SchemaDefinition struct { | |
Type string `json:",omitempty"` | |
Optional bool `json:",omitempty"` | |
Required bool `json:",omitempty"` | |
Description string `json:",omitempty"` | |
InputDefault string `json:",omitempty"` | |
Computed bool `json:",omitempty"` | |
MaxItems int `json:",omitempty"` | |
MinItems int `json:",omitempty"` | |
PromoteSingle bool `json:",omitempty"` | |
ComputedWhen []string `json:",omitempty"` | |
ConflictsWith []string `json:",omitempty"` | |
Deprecated string `json:",omitempty"` | |
Removed string `json:",omitempty"` | |
Default SchemaElement `json:",omitempty"` | |
Elem SchemaElement `json:",omitempty"` | |
} | |
type SchemaInfo map[string]SchemaDefinition | |
// ResourceProviderSchema | |
type ResourceProviderSchema struct { | |
Name string `json:"name"` | |
Type string `json:"type"` | |
Version string `json:"version"` | |
Provider SchemaInfo `json:"provider"` | |
Resources map[string]SchemaInfo `json:"resources"` | |
DataSources map[string]SchemaInfo `json:"data-sources"` | |
} | |
func main() { | |
var provider tf.ResourceProvider | |
provider = __NAME__.Provider() | |
Generate(provider.(*schema.Provider), "__NAME__", "__OUT__") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment