1 Star 0 Fork 2

安易科技(北京)有限公司/chameleon

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
enumerator.go 4.47 KB
一键复制 编辑 原始数据 按行查看 历史
Derek Ray 提交于 2025-03-21 18:49 +08:00 . feat(template): update template sources
package template
import (
"bytes"
"compress/gzip"
"context"
"errors"
"fmt"
"gitee.com/anesec/chameleon/pkg/template/expr"
"gitee.com/anesec/chameleon/pkg/template/language"
"gitee.com/anesec/chameleon/pkg/utils"
"go.etcd.io/bbolt"
"path/filepath"
"sort"
"sync"
"time"
)
type Kind uint8
const (
KindUnknown Kind = iota
KindApplication
KindFramework
)
var (
ErrNotMatch = errors.New("not match")
)
type EnumerateOptions struct {
Templates []string
}
type Enumerator interface {
Enumerate(ctx context.Context, source expr.Source, options *EnumerateOptions) error
}
func Compile(templates ...string) (Enumerator, error) {
var (
services []*Template
languages []*Template
err error
)
enum := &enumerator{}
if services, languages, err = enum.compile(templates...); err != nil {
return nil, err
}
enum.services = services
enum.languages = languages
return enum, nil
}
type enumerator struct {
services []*Template
languages []*Template
rwl sync.RWMutex
}
func (enum *enumerator) Enumerate(ctx context.Context, source expr.Source, options *EnumerateOptions) error {
var (
services []*Template
languages []*Template
service *Template
err error
)
if options == nil {
options = &EnumerateOptions{}
}
if len(options.Templates) > 0 {
if services, languages, err = enum.compile(options.Templates...); err != nil {
return err
}
} else {
services = enum.services
languages = enum.languages
}
// enumerate AI service first
sort.Sort(templates(services))
var llmServiceFound bool
source = language.New(source)
for _, template := range services {
if llmServiceFound && template.Category == "ai" {
continue
}
if template.eval(ctx, source, KindApplication) {
if template.Category == "ai" {
// found AI llm service, continue to enumerate web/application... services
llmServiceFound = true
continue
}
service = template
break
}
}
if service == nil {
if llmServiceFound {
return nil
}
return ErrNotMatch
}
ports, _ := source.Provide("proc.ports").([]int)
if (service.Category == "web" || len(ports) > 0) && len(languages) > 0 {
lang, ok := source.Provide("distribute.language").(string)
if !ok || lang == "" {
return nil
}
for _, template := range languages {
if template.Name != lang {
continue
}
template.eval(ctx, source, KindFramework)
}
}
return nil
}
func (enum *enumerator) compile(templates ...string) (services, languages []*Template, err error) {
services = make([]*Template, 0, len(templates))
languages = make([]*Template, 0, len(templates))
buf := utils.Acquire(utils.BufferSize2K)
defer utils.Recycle(buf)
for _, template := range templates {
switch filepath.Ext(template) {
case ".yaml", ".yml":
buf.Reset()
if err = utils.BufferedRead(template, buf); err != nil {
return
}
var tpl Template
if err = tpl.compile(buf); err != nil {
return
}
switch enum.detectTemplateKind(&tpl) {
case KindApplication:
services = append(services, &tpl)
case KindFramework:
languages = append(languages, &tpl)
default:
}
case ".templates":
var db *bbolt.DB
if db, err = bbolt.Open(template, 0600, &bbolt.Options{ReadOnly: true, Timeout: 15 * time.Second}); err != nil {
return
}
err = db.View(func(tx *bbolt.Tx) error {
bkt := tx.Bucket([]byte("templates"))
if bkt == nil {
return fmt.Errorf("no templates bucket in file %s", template)
}
return bkt.ForEach(func(k, v []byte) error {
var gzipReader *gzip.Reader
if gzipReader, err = gzip.NewReader(bytes.NewReader(v)); err != nil {
return err
}
defer gzipReader.Close()
var tpl Template
if err = tpl.compile(gzipReader); err != nil {
return err
}
switch enum.detectTemplateKind(&tpl) {
case KindApplication:
services = append(services, &tpl)
case KindFramework:
languages = append(languages, &tpl)
default:
}
return nil
})
})
_ = db.Close()
if err != nil {
return
}
default:
return nil, nil, fmt.Errorf("unknown template type: %s", filepath.Ext(template))
}
}
return
}
func (enum *enumerator) detectTemplateKind(template *Template) Kind {
switch template.Name {
case language.Python, language.Java, language.Golang, language.NodeJS, language.Node, language.PHP:
if template.Frameworks != nil {
return KindFramework
}
}
if template.Service != nil && template.Frameworks == nil {
return KindApplication
}
return KindUnknown
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/anesec/chameleon.git
git@gitee.com:anesec/chameleon.git
anesec
chameleon
chameleon
205da4a0ed50

搜索帮助