<commit_before>package velocity

import (
	"context"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"sync"
	"time"

	"github.com/docker/go/canonical/json"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
)

type Parameter struct {
	Name     string `json:"name"`
	Value    string `json:"value"`
	IsSecret bool   `json:"isSecret"`
}

type ConfigParameter interface {
	GetInfo() string
	GetParameters(writer io.Writer, runID string, backupResolver BackupResolver) ([]Parameter, error)
}

type BackupResolver interface {
	Resolve(paramName string) (string, error)
}

type BasicParameter struct {
	Name         string   `json:"name" yaml:"name"`
	Default      string   `json:"default" yaml:"default"`
	OtherOptions []string `json:"otherOptions" yaml:"otherOptions"`
	Secret       bool     `json:"secret" yaml:"secret"`
	Value        string   `json:"value"`
}

func (p BasicParameter) GetInfo() string {
	return p.Name
}

func (p BasicParameter) GetParameters(writer io.Writer, runID string, backupResolver BackupResolver) ([]Parameter, error) {
	v := p.Default
	if len(p.Value) > 0 {
		v = p.Value
	}
	return []Parameter{
		Parameter{
			Name:     p.Name,
			Value:    v,
			IsSecret: p.Secret,
		},
	}, nil
}

func (p *BasicParameter) UnmarshalYamlInterface(y map[interface{}]interface{}) error {
	switch x := y["name"].(type) {
	case interface{}:
		p.Name = x.(string)
		break
	}
	switch x := y["default"].(type) {
	case interface{}:
		p.Default = x.(string)
		break
	}
	switch x := y["secret"].(type) {
	case interface{}:
		p.Secret = x.(bool)
		break
	}

	p.OtherOptions = []string{}
	switch x := y["otherOptions"].(type) {
	case []interface{}:
		for _, o := range x {
			p.OtherOptions = append(p.OtherOptions, o.(string))
		}
		break
	}

	return nil
}

type DerivedParameter struct {
	Use       string            `json:"use" yaml:"use"`
	Secret    bool              `json:"secret" yaml:"secret"`
	Arguments map[string]string `json:"arguments" yaml:"arguments"`
	Exports   map[string]string `json:"exports" yaml:"exports"`
	// Timeout   uint64
}

func (p DerivedParameter) GetInfo() string {
	return p.Use
}

func (p DerivedParameter) GetParameters(writer io.Writer, runID string, backupResolver BackupResolver) ([]Parameter, error) {
	env := []string{}
	for k, v := range p.Arguments {
		env = append(env, fmt.Sprintf("%s=%s", k, v))
	}
	containerConfig := &container.Config{
		Image: p.Use,
		Env:   env,
	}

	var wg sync.WaitGroup
	cli, _ := client.NewEnvClient()
	ctx := context.Background()

	networkResp, err := cli.NetworkCreate(ctx, runID, types.NetworkCreate{
		Labels: map[string]string{"owner": "velocity-ci"},
	})
	if err != nil {
		log.Println(err)
	}
	blankEmitter := NewBlankEmitter()
	w := blankEmitter.GetStreamWriter("setup")
	sR := newServiceRunner(
		cli,
		ctx,
		w,
		&wg,
		map[string]Parameter{},
		fmt.Sprintf("%s-%s", runID, "dParam"),
		p.Use,
		nil,
		containerConfig,
		nil,
		nil,
		networkResp.ID,
	)

	sR.PullOrBuild()
	sR.Create()
	stopServicesChannel := make(chan string, 32)
	wg.Add(1)
	go sR.Run(stopServicesChannel)
	_ = <-stopServicesChannel

	logsResp, err := sR.dockerCli.ContainerLogs(
		sR.context,
		sR.containerID,
		types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: false},
	)
	if err != nil {
		log.Printf("param container %s logs err: %s", sR.containerID, err)
	}
	headerBytes := make([]byte, 8)
	logsResp.Read(headerBytes)
	content, _ := ioutil.ReadAll(logsResp)
	logsResp.Close()
	sR.Stop()
	wg.Wait()
	err = cli.NetworkRemove(ctx, networkResp.ID)
	if err != nil {
		log.Printf("network %s remove err: %s", networkResp.ID, err)
	}

	params := []Parameter{}
	var dOutput derivedOutput
	json.Unmarshal(content, &dOutput)
	if dOutput.State == "warning" {
		for paramName := range dOutput.Exports {
			val, err := backupResolver.Resolve(paramName)
			if err != nil {
				return []Parameter{}, err
			}
			params = append(params, Parameter{
				Name:     paramName,
				Value:    val,
				IsSecret: dOutput.Secret,
			})
		}
	} else if dOutput.State == "success" {
		for paramName, val := range dOutput.Exports {
			params = append(params, Parameter{
				Name:     paramName,
				Value:    val,
				IsSecret: dOutput.Secret,
			})
		}
	} else { // failed
		return []Parameter{}, errors.New(dOutput.Error)
	}

	return params, nil
}

func (p *DerivedParameter) UnmarshalYamlInterface(y map[interface{}]interface{}) error {

	switch x := y["use"].(type) {
	case interface{}:
		p.Use = x.(string)
		break<commit_msg>[backend] Added a type field to parameters<commit_after>package velocity

import (
	"context"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"sync"
	"time"

	"github.com/docker/go/canonical/json"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
)

type Parameter struct {
	Name     string `json:"name"`
	Value    string `json:"value"`
	IsSecret bool   `json:"isSecret"`
}

type ConfigParameter interface {
	GetInfo() string
	GetParameters(writer io.Writer, runID string, backupResolver BackupResolver) ([]Parameter, error)
}

type BackupResolver interface {
	Resolve(paramName string) (string, error)
}

type BasicParameter struct {
	Type         string   `json:"type"`
	Name         string   `json:"name" yaml:"name"`
	Default      string   `json:"default" yaml:"default"`
	OtherOptions []string `json:"otherOptions" yaml:"otherOptions"`
	Secret       bool     `json:"secret" yaml:"secret"`
	Value        string   `json:"value"`
}

func (p BasicParameter) GetInfo() string {
	return p.Name
}

func (p BasicParameter) GetParameters(writer io.Writer, runID string, backupResolver BackupResolver) ([]Parameter, error) {
	v := p.Default
	if len(p.Value) > 0 {
		v = p.Value
	}
	return []Parameter{
		Parameter{
			Name:     p.Name,
			Value:    v,
			IsSecret: p.Secret,
		},
	}, nil
}

func (p *BasicParameter) UnmarshalYamlInterface(y map[interface{}]interface{}) error {
	p.Type = "basic"
	switch x := y["name"].(type) {
	case interface{}:
		p.Name = x.(string)
		break
	}
	switch x := y["default"].(type) {
	case interface{}:
		p.Default = x.(string)
		break
	}
	switch x := y["secret"].(type) {
	case interface{}:
		p.Secret = x.(bool)
		break
	}

	p.OtherOptions = []string{}
	switch x := y["otherOptions"].(type) {
	case []interface{}:
		for _, o := range x {
			p.OtherOptions = append(p.OtherOptions, o.(string))
		}
		break
	}

	return nil
}

type DerivedParameter struct {
	Type      string            `json:"type"`
	Use       string            `json:"use" yaml:"use"`
	Secret    bool              `json:"secret" yaml:"secret"`
	Arguments map[string]string `json:"arguments" yaml:"arguments"`
	Exports   map[string]string `json:"exports" yaml:"exports"`
	// Timeout   uint64
}

func (p DerivedParameter) GetInfo() string {
	return p.Use
}

func (p DerivedParameter) GetParameters(writer io.Writer, runID string, backupResolver BackupResolver) ([]Parameter, error) {
	env := []string{}
	for k, v := range p.Arguments {
		env = append(env, fmt.Sprintf("%s=%s", k, v))
	}
	containerConfig := &container.Config{
		Image: p.Use,
		Env:   env,
	}

	var wg sync.WaitGroup
	cli, _ := client.NewEnvClient()
	ctx := context.Background()

	networkResp, err := cli.NetworkCreate(ctx, runID, types.NetworkCreate{
		Labels: map[string]string{"owner": "velocity-ci"},
	})
	if err != nil {
		log.Println(err)
	}
	blankEmitter := NewBlankEmitter()
	w := blankEmitter.GetStreamWriter("setup")
	sR := newServiceRunner(
		cli,
		ctx,
		w,
		&wg,
		map[string]Parameter{},
		fmt.Sprintf("%s-%s", runID, "dParam"),
		p.Use,
		nil,
		containerConfig,
		nil,
		nil,
		networkResp.ID,
	)

	sR.PullOrBuild()
	sR.Create()
	stopServicesChannel := make(chan string, 32)
	wg.Add(1)
	go sR.Run(stopServicesChannel)
	_ = <-stopServicesChannel

	logsResp, err := sR.dockerCli.ContainerLogs(
		sR.context,
		sR.containerID,
		types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: false},
	)
	if err != nil {
		log.Printf("param container %s logs err: %s", sR.containerID, err)
	}
	headerBytes := make([]byte, 8)
	logsResp.Read(headerBytes)
	content, _ := ioutil.ReadAll(logsResp)
	logsResp.Close()
	sR.Stop()
	wg.Wait()
	err = cli.NetworkRemove(ctx, networkResp.ID)
	if err != nil {
		log.Printf("network %s remove err: %s", networkResp.ID, err)
	}

	params := []Parameter{}
	var dOutput derivedOutput
	json.Unmarshal(content, &dOutput)
	if dOutput.State == "warning" {
		for paramName := range dOutput.Exports {
			val, err := backupResolver.Resolve(paramName)
			if err != nil {
				return []Parameter{}, err
			}
			params = append(params, Parameter{
				Name:     paramName,
				Value:    val,
				IsSecret: dOutput.Secret,
			})
		}
	} else if dOutput.State == "success" {
		for paramName, val := range dOutput.Exports {
			params = append(params, Parameter{
				Name:     paramName,
				Value:    val,
				IsSecret: dOutput.Secret,
			})
		}
	} else { // failed
		return []Parameter{}, errors.New(dOutput.Error)
	}

	return params, nil
}

func (p *DerivedParameter) UnmarshalYamlInterface(y map[interface{}]interface{}) error {

	p.Type = "derived"

	switch x := y["use"].(type) {
	case interface{}:
		p.Use = x.(string)
		break
{'fraction_non_alphanumeric': 0.15169876650075742, 'fraction_numerical': 0.0015148236312486475, 'mean_word_length': 3.74, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1182312', 'n_tokens_mistral': 3492, 'n_tokens_neox': 3229, 'n_words': 761}