hgctl/pkg/plugin/init/templates.go (249 lines of code) (raw):
// Copyright (c) 2022 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plugininit
import (
"fmt"
"os"
"text/template"
"github.com/AlecAivazis/survey/v2"
"github.com/alibaba/higress/hgctl/pkg/plugin/types"
)
const (
goMain = `// File generated by hgctl. Modify as required.
// See: https://higress.io/zh-cn/docs/user/wasm-go#2-%E7%BC%96%E5%86%99-maingo-%E6%96%87%E4%BB%B6
package main
import (
"github.com/tidwall/gjson"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
)
func main() {
wrapper.SetCtx(
"{{ .Name }}",
wrapper.ParseConfigBy(parseConfig),
wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
)
}
// @Name {{ .Name }}
// @Category {{ .Category }}
// @Phase {{ .Phase }}
// @Priority {{ .Priority }}
// @Title {{ .I18nType }} {{ .Title }}
// @Description {{ .I18nType }} {{ .Description }}
// @IconUrl {{ .IconUrl }}
// @Version {{ .Version }}
//
// @Contact.name {{ .ContactName }}
// @Contact.url {{ .ContactUrl }}
// @Contact.email {{ .ContactEmail }}
//
// @Example
// firstField: hello
// secondField: world
// @End
//
type PluginConfig struct {
// @Title 第一个字段,注解格式为 @Title [语言] [标题],语言缺省值为 en-US
// @Description 字符串的前半部分,注解格式为 @Description [语言] [描述],语言缺省值为 en-US
firstField string ` + "`required:\"true\"`" + `
// @Title en-US Second Field, annotation format is @Title [language] [title], language defaults to en-US
// @Description en-US The second half of the string, annotation format is @Description [language] [description], language defaults to en-US
secondField string ` + "`required:\"true\"`" + `
}
func parseConfig(json gjson.Result, config *PluginConfig, log wrapper.Log) error {
config.firstField = json.Get("firstField").String()
config.secondField = json.Get("secondField").String()
return nil
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config PluginConfig, log wrapper.Log) types.Action {
err := proxywasm.AddHttpRequestHeader(config.firstField, config.secondField)
if err != nil {
log.Critical("failed to set request header")
}
return types.ActionContinue
}
`
goMod = `// File generated by hgctl. Modify as required.
module {{ .Name }}
go 1.19
require (
github.com/alibaba/higress/plugins/wasm-go main
github.com/higress-group/proxy-wasm-go-sdk main
github.com/tidwall/gjson v1.14.3
)
`
gitIgnore = `# File generated by hgctl. Modify as required.
*
!/.gitignore
!*.go
!go.sum
!go.mod
!LICENSE
!*.md
!*.yaml
!*.yml
!*/
/out
/test
`
)
func genGoMain(ans *answer, dir string) error {
path := fmt.Sprintf("%s/main.go", dir)
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if err = template.Must(template.New("GoMain").Parse(goMain)).Execute(f, ans); err != nil {
return err
}
return nil
}
func genGoMod(ans *answer, dir string) error {
path := fmt.Sprintf("%s/go.mod", dir)
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if err = template.Must(template.New("GoMod").Parse(goMod)).Execute(f, ans); err != nil {
return err
}
return nil
}
func genGitIgnore(dir string) error {
path := fmt.Sprintf("%s/.gitignore", dir)
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if _, err = f.WriteString(gitIgnore); err != nil {
return err
}
return nil
}
// obtain parameters through command line interaction
type answer struct {
Name string
Category string
Phase string
Priority int64
I18nType string
Title string
Description string
IconUrl string
Version string
ContactName string
ContactUrl string
ContactEmail string
}
var questions = []*survey.Question{
{
Name: "Name",
Prompt: &survey.Input{
Message: "Plugin name:",
Default: "hello-world",
},
Validate: survey.Required,
},
{
Name: "Category",
Prompt: &survey.Select{
Message: "Choose a plugin category:",
Options: []string{
string(types.CategoryCustom),
string(types.CategoryAuth),
string(types.CategorySecurity),
string(types.CategoryProtocol),
string(types.CategoryFlowControl),
string(types.CategoryFlowMonitor),
},
Default: string(types.CategoryCustom),
},
Validate: survey.Required,
},
{
Name: "Phase",
Prompt: &survey.Select{
Message: "Choose a execution phase:",
Options: []string{
string(types.PhaseUnspecified),
string(types.PhaseAuthn),
string(types.PhaseAuthz),
string(types.PhaseStats),
},
Default: string(types.PhaseUnspecified),
},
Validate: survey.Required,
},
{
Name: "Priority",
Prompt: &survey.Input{
Message: "Execution priority:",
Default: "0",
},
Validate: survey.Required,
},
{
Name: "I18nType",
Prompt: &survey.Select{
Message: "Choose a language:",
Options: []string{
string(types.I18nEN_US),
string(types.I18nZH_CN),
},
Default: string(types.I18nDefault),
},
Validate: survey.Required,
},
{
Name: "Title",
Prompt: &survey.Input{
Message: "Display name in the plugin market:",
Default: "Hello World",
},
Validate: survey.Required,
},
{
Name: "Description",
Prompt: &survey.Input{
Message: "Description of the plugin functionality:",
Default: "This is a demo plugin",
},
},
{
Name: "IconUrl",
Prompt: &survey.Input{
Message: "Display icon in the plugin market:",
Default: "",
},
},
{
Name: "Version",
Prompt: &survey.Input{
Message: "Plugin version:",
Default: "0.1.0",
},
Validate: survey.Required,
},
{
Name: "ContactName",
Prompt: &survey.Input{
Message: "Name of developer:",
Default: "",
},
},
{
Name: "ContactUrl",
Prompt: &survey.Input{
Message: "Homepage of developer:",
Default: "",
},
},
{
Name: "ContactEmail",
Prompt: &survey.Input{
Message: "Email of developer:",
Default: "",
},
},
}