<commit_before>package workflows

import (
	"encoding/base64"
	"fmt"
	"os"
	"strings"

	"github.com/docker/docker/api/types"
	"github.com/pkg/errors"
	"github.com/stelligent/mu/common"
)

type serviceWorkflow struct {
	envStack                      *common.Stack
	lbStack                       *common.Stack
	artifactProvider              common.ArtifactProvider
	serviceName                   string
	serviceTag                    string
	serviceImage                  string
	registryAuth                  string
	registryAuthConfig            map[string]types.AuthConfig
	priority                      int
	codeRevision                  string
	repoName                      string
	appName                       string
	appRevisionBucket             string
	appRevisionKey                string
	databaseName                  string
	cloudFormationRoleArn         string
	microserviceTaskDefinitionArn string
	ecsEventsRoleArn              string
	kubernetesResourceManager     common.KubernetesResourceManager
}

// Find a service in config, by name and set the reference
func (workflow *serviceWorkflow) serviceLoader(ctx *common.Context, tag string, provider string) Executor {
	return func() error {
		err := workflow.serviceInput(ctx, "")()
		if err != nil {
			return err
		}

		// Tag
		if tag != "" {
			workflow.serviceTag = tag
		} else if ctx.Config.Repo.Revision != "" {
			workflow.serviceTag = ctx.Config.Repo.Revision
		} else {
			workflow.serviceTag = "latest"
		}
		workflow.appRevisionKey = fmt.Sprintf("%s/%s.zip", workflow.serviceName, workflow.serviceTag)

		workflow.databaseName = ctx.Config.Service.Database.Name
		workflow.codeRevision = ctx.Config.Repo.Revision
		workflow.repoName = ctx.Config.Repo.Slug
		workflow.priority = ctx.Config.Service.Priority

		if provider == "" {
			dockerfile := ctx.Config.Service.Dockerfile
			if dockerfile == "" {
				dockerfile = "Dockerfile"
			}

			dockerfilePath := fmt.Sprintf("%s/%s", ctx.Config.Basedir, dockerfile)
			log.Debugf("Determining repo provider by checking for existence of '%s'", dockerfilePath)

			if _, err := os.Stat(dockerfilePath); !os.IsNotExist(err) {
				log.Infof("Dockerfile found, assuming ECR pipeline")
				workflow.artifactProvider = common.ArtifactProviderEcr
			} else {
				log.Infof("No Dockerfile found, assuming CodeDeploy pipeline")
				workflow.artifactProvider = common.ArtifactProviderS3
			}
		} else {
			workflow.artifactProvider = common.ArtifactProvider(provider)
		}

		log.Debugf("Working with service:'%s' tag:'%s'", workflow.serviceName, workflow.serviceTag)
		return nil
	}
}

func (workflow *serviceWorkflow) isEcrProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.artifactProvider), string(common.ArtifactProviderEcr))
	}
}

func (workflow *serviceWorkflow) isS3Provider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.artifactProvider), string(common.ArtifactProviderS3))
	}
}

func (workflow *serviceWorkflow) isEcsProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEcs)) ||
			strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEcsFargate))
	}
}
func (workflow *serviceWorkflow) isEksProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEks)) ||
			strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEksFargate))
	}
}
func (workflow *serviceWorkflow) isFargateProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEcsFargate))
	}
}

func (workflow *serviceWorkflow) isEc2Provider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEc2))
	}
}

func (workflow *serviceWorkflow) serviceInput(ctx *common.Context, serviceName string) Executor {
	return func() error {
		// Repo Name
		if serviceName != "" {
			workflow.serviceName = serviceName
		} else if ctx.Config.Service.Name != "" {
			workflow.serviceName = ctx.Config.Service.Name
		} else if ctx.Config.Repo.Name != "" {
			workflow.serviceName = ctx.Config.Repo.Name
		} else {
			return errors.New("Service name must be provided")
		}
		return nil
	}
}

func (workflow *serviceWorkflow) serviceRepoUpserter(namespace string, service *common.Service, stackUpserter common.StackUpserter, stackWaiter common.StackWaiter) Executor {
	return func() error {
		if service.ImageRepository != "" {
			log.Noticef("Using repo '%s' for service '%s'", service.ImageRepository, workflow.serviceName)
			workflow.serviceImage = service.ImageRepository
			return nil
		}

		log.Noticef("Upsert repo for service '%s'", workflow.serviceName)

		ecrStackName := common.CreateStackName(namespace, common.StackTypeRepo, workflow.serviceName)

		stackParams := make(map[string]string)
		stackParams["RepoName"] = fmt.Sprintf("%s-%s", namespace, workflow.serviceName)

		tags := createTagMap(&ServiceTags{
			Service:  workflow.serviceName,
			Type:     string(common.StackTypeRepo),
			Provider: "",
			Revision: workflow.codeRevision,
			Repo:     workflow.repoName,
		})

		err := stackUpserter.UpsertStack(ecrStackName, common.TemplateRepo, nil, stackParams, tags, "", "")
		if err != nil {
			return err
		}

		log.Debugf("Waiting for stack '%s' to complete", ecrStackName)
		stack := stackWaiter.AwaitFinalStatus(ecrStackName)
		if stack == nil {
			return fmt.Errorf("Unable to create stack %s", ecrStackName)
		}
		if strings.HasSuffix(stack.Status, "ROLLBACK_COMPLETE") || !strings.HasSuffix(stack.Status, "_COMPLETE") {
			return fmt.Errorf("Ended in failed status %s %s", stack.Status, stack.StatusReason)
		}
		workflow.serviceImage = fmt.Sprintf("%s:%s", stack.Outputs["RepoUrl"], workflow.serviceTag)
		return nil
	}
}
func (workflow *serviceWorkflow) serviceAppUpserter(namespace string, service *common.Service, stackUpserter common.StackUpserter, stackWaiter common.StackWaiter) Executor {
	return func() error {
		log.Noticef("Upsert app for service '%s'", workflow.serviceName)

		appStackName := common.CreateStackName(namespace, common.StackTypeApp, workflow.serviceName)

		stackParams := make(map[string]string)

		tags := createTagMap(&EnvironmentTags{
			Environment: workflow.serviceName,
			Type:        string(common.StackTypeApp),
			Provider:    "",
			Revision:    workflow.codeRevision,
			Repo:        workflow.repoName,
		})

		err := stackUpserter.UpsertStack(appStackName, common.TemplateApp, nil, stackParams, tags, "", workflow.cloudFormationRoleArn)
		if err != nil {
			return err
		}

		log.Debugf("Waiting for stack '%s' to complete", appStackName)
		stack := stackWaiter.AwaitFinalStatus(appStackName)
		if stack == nil {
			return fmt.Errorf("Unable to create stack %s", appStackName)
		}
		if strings.HasSuffix(stack.Status, "ROLLBACK_COMPLETE") || !strings.HasSuffix(stack.Status, "_COMPLETE") {
			return fmt.Errorf("Ended in failed status %s %s", stack.Status, stack.StatusReason)
		}
		workflow.appName = stack.Outputs["ApplicationName"]
		return nil
	}
}

func (workflow *serviceWorkflow) serviceBucketUpserter(namespace string, service *common.Service, stackUpserter common.StackUpserter, stackWaiter common.StackWaiter) Executor {
	return func() error {

		if service.Pipeline.Build.Bucket != "" {
			workflow.appRevisionBucket = service.Pipeline.Build.Bucket
		} else {
			bucketStackName := common.CreateStackName(namespace, common.StackTypeBucket, "codedeploy")
			log.Noticef("Upserting Bucket for CodeDeploy")
			bucketParams := make(map[string]string)
			bucketParams["Namespace"] = namespace
			bucketParams["BucketPrefix"] = "codedeploy"

			tags := createTagMap(&PipelineTags{
				Type: common.StackTypeBucket,
			})

			err := stackUpserter.UpsertStack(bucketStackName, common.TemplateBucket, nil, bucketParams, tags, "", workflow.cloudFormationRoleArn)
			if err != nil {
				return err
			}

			log.Debugf("Waiting for stack '%s' to complete", bucketStackName)
			stack := stackWaiter.AwaitFinalStatus(bucketStackName)
			if stack == nil {
				return fmt.Errorf("Unable to create stack %s", bucketStackName)
			}
			if strings.HasSuffix(stack.Status, "ROLLBACK_COMPLETE") || !strings.HasSuffix(stack.Status, "_COMPLETE") {
				return fmt.Errorf("Ended in failed status %s %s", stack.Status, stack.StatusReason)
			}

			workflow.appRevisionBucket = stack.Outputs["Bucket"]

		}

		return nil
	}
}

func (workflow *serviceWorkflow) serviceRegistryAuthenticator(authenticator common.RepositoryAuthenticator) Executor {
	return func() error {
		log.Debugf("Authenticating to registry '%s'", workflow.serviceImage)
		registryAuth, err := authenticator.AuthenticateRepository(workflow.serviceImage)
		if err != nil {
			return err
		}

		data, err := base64.StdEncoding.DecodeString(registryAuth)
		if err != nil {
			return err
		}

		authParts := strings.Split(string(data), ":")

		workflow.registryAuth = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("{\"username\":\"%s\", \"password\":\"%s\"}", authParts[0], authParts[1])))

		// ImageBuild pull auth
		var authConfigs2 map[string]types.AuthConfig = make(map[string]types.AuthConfig)
		var serviceImagePart = strings.Split(workflow.serviceImage, ":")[0]

		authConfigs2[serviceImagePart] = types.AuthConfig{
			Username:      authParts[0],
			Password:      authParts[1],
			ServerAddress: fmt.Sprintf("https://%s", serviceImagePart),
		}

		workflow.registryAuthConfig = authConfigs2

		return nil
	}
}

func (workflow *serviceWorkflow) connectKubernetes(provider common.KubernetesResourceManagerProvider) Executor {
	return func() error {
		clusterName := workflow.envStack.Name
		kubernetesResourceManager, err := provider.GetResourceManager(clusterName)
		workflow.kubernetesResourceManager = kubernetesResourceManager
		return err
	}
}
<commit_msg>cleanup<commit_after>package workflows

import (
	"encoding/base64"
	"fmt"
	"os"
	"strings"

	"github.com/docker/docker/api/types"
	"github.com/pkg/errors"
	"github.com/stelligent/mu/common"
)

type serviceWorkflow struct {
	envStack                      *common.Stack
	lbStack                       *common.Stack
	artifactProvider              common.ArtifactProvider
	serviceName                   string
	serviceTag                    string
	serviceImage                  string
	registryAuth                  string
	registryAuthConfig            map[string]types.AuthConfig
	priority                      int
	codeRevision                  string
	repoName                      string
	appName                       string
	appRevisionBucket             string
	appRevisionKey                string
	databaseName                  string
	cloudFormationRoleArn         string
	microserviceTaskDefinitionArn string
	ecsEventsRoleArn              string
	kubernetesResourceManager     common.KubernetesResourceManager
}

// Find a service in config, by name and set the reference
func (workflow *serviceWorkflow) serviceLoader(ctx *common.Context, tag string, provider string) Executor {
	return func() error {
		err := workflow.serviceInput(ctx, "")()
		if err != nil {
			return err
		}

		// Tag
		if tag != "" {
			workflow.serviceTag = tag
		} else if ctx.Config.Repo.Revision != "" {
			workflow.serviceTag = ctx.Config.Repo.Revision
		} else {
			workflow.serviceTag = "latest"
		}
		workflow.appRevisionKey = fmt.Sprintf("%s/%s.zip", workflow.serviceName, workflow.serviceTag)

		workflow.databaseName = ctx.Config.Service.Database.Name
		workflow.codeRevision = ctx.Config.Repo.Revision
		workflow.repoName = ctx.Config.Repo.Slug
		workflow.priority = ctx.Config.Service.Priority

		if provider == "" {
			dockerfile := ctx.Config.Service.Dockerfile
			if dockerfile == "" {
				dockerfile = "Dockerfile"
			}

			dockerfilePath := fmt.Sprintf("%s/%s", ctx.Config.Basedir, dockerfile)
			log.Debugf("Determining repo provider by checking for existence of '%s'", dockerfilePath)

			if _, err := os.Stat(dockerfilePath); !os.IsNotExist(err) {
				log.Infof("Dockerfile found, assuming ECR pipeline")
				workflow.artifactProvider = common.ArtifactProviderEcr
			} else {
				log.Infof("No Dockerfile found, assuming CodeDeploy pipeline")
				workflow.artifactProvider = common.ArtifactProviderS3
			}
		} else {
			workflow.artifactProvider = common.ArtifactProvider(provider)
		}

		log.Debugf("Working with service:'%s' tag:'%s'", workflow.serviceName, workflow.serviceTag)
		return nil
	}
}

func (workflow *serviceWorkflow) isEcrProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.artifactProvider), string(common.ArtifactProviderEcr))
	}
}

func (workflow *serviceWorkflow) isS3Provider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.artifactProvider), string(common.ArtifactProviderS3))
	}
}

func (workflow *serviceWorkflow) isEcsProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEcs)) ||
			strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEcsFargate))
	}
}
func (workflow *serviceWorkflow) isEksProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEks)) ||
			strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEksFargate))
	}
}
func (workflow *serviceWorkflow) isFargateProvider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEcsFargate))
	}
}

func (workflow *serviceWorkflow) isEc2Provider() Conditional {
	return func() bool {
		return strings.EqualFold(string(workflow.envStack.Tags["provider"]), string(common.EnvProviderEc2))
	}
}

func (workflow *serviceWorkflow) serviceInput(ctx *common.Context, serviceName string) Executor {
	return func() error {
		// Repo Name
		if serviceName != "" {
			workflow.serviceName = serviceName
		} else if ctx.Config.Service.Name != "" {
			workflow.serviceName = ctx.Config.Service.Name
		} else if ctx.Config.Repo.Name != "" {
			workflow.serviceName = ctx.Config.Repo.Name
		} else {
			return errors.New("Service name must be provided")
		}
		return nil
	}
}

func (workflow *serviceWorkflow) serviceRepoUpserter(namespace string, service *common.Service, stackUpserter common.StackUpserter, stackWaiter common.StackWaiter) Executor {
	return func() error {
		if service.ImageRepository != "" {
			log.Noticef("Using repo '%s' for service '%s'", service.ImageRepository, workflow.serviceName)
			workflow.serviceImage = service.ImageRepository
			return nil
		}

		log.Noticef("Upsert repo for service '%s'", workflow.serviceName)

		ecrStackName := common.CreateStackName(namespace, common.StackTypeRepo, workflow.serviceName)

		stackParams := make(map[string]string)
		stackParams["RepoName"] = fmt.Sprintf("%s-%s", namespace, workflow.serviceName)

		tags := createTagMap(&ServiceTags{
			Service:  workflow.serviceName,
			Type:     string(common.StackTypeRepo),
			Provider: "",
			Revision: workflow.codeRevision,
			Repo:     workflow.repoName,
		})

		err := stackUpserter.UpsertStack(ecrStackName, common.TemplateRepo, nil, stackParams, tags, "", "")
		if err != nil {
			return err
		}

		log.Debugf("Waiting for stack '%s' to complete", ecrStackName)
		stack := stackWaiter.AwaitFinalStatus(ecrStackName)
		if stack == nil {
			return fmt.Errorf("Unable to create stack %s", ecrStackName)
		}
		if strings.HasSuffix(stack.Status, "ROLLBACK_COMPLETE") || !strings.HasSuffix(stack.Status, "_COMPLETE") {
			return fmt.Errorf("Ended in failed status %s %s", stack.Status, stack.StatusReason)
		}
		workflow.serviceImage = fmt.Sprintf("%s:%s", stack.Outputs["RepoUrl"], workflow.serviceTag)
		return nil
	}
}
func (workflow *serviceWorkflow) serviceAppUpserter(namespace string, service *common.Service, stackUpserter common.StackUpserter, stackWaiter common.StackWaiter) Executor {
	return func() error {
		log.Noticef("Upsert app for service '%s'", workflow.serviceName)

		appStackName := common.CreateStackName(namespace, common.StackTypeApp, workflow.serviceName)

		stackParams := make(map[string]string)

		tags := createTagMap(&EnvironmentTags{
			Environment: workflow.serviceName,
			Type:        string(common.StackTypeApp),
			Provider:    "",
			Revision:    workflow.codeRevision,
			Repo:        workflow.repoName,
		})

		err := stackUpserter.UpsertStack(appStackName, common.TemplateApp, nil, stackParams, tags, "", workflow.cloudFormationRoleArn)
		if err != nil {
			return err
		}

		log.Debugf("Waiting for stack '%s' to complete", appStackName)
		stack := stackWaiter.AwaitFinalStatus(appStackName)
		if stack == nil {
			return fmt.Errorf("Unable to create stack %s", appStackName)
		}
		if strings.HasSuffix(stack.Status, "ROLLBACK_COMPLETE") || !strings.HasSuffix(stack.Status, "_COMPLETE") {
			return fmt.Errorf("Ended in failed status %s %s", stack.Status, stack.StatusReason)
		}
		workflow.appName = stack.Outputs["ApplicationName"]
		return nil
	}
}

func (workflow *serviceWorkflow) serviceBucketUpserter(namespace string, service *common.Service, stackUpserter common.StackUpserter, stackWaiter common.StackWaiter) Executor {
	return func() error {

		if service.Pipeline.Build.Bucket != "" {
			workflow.appRevisionBucket = service.Pipeline.Build.Bucket
		} else {
			bucketStackName := common.CreateStackName(namespace, common.StackTypeBucket, "codedeploy")
			log.Noticef("Upserting Bucket for CodeDeploy")
			bucketParams := make(map[string]string)
			bucketParams["Namespace"] = namespace
			bucketParams["BucketPrefix"] = "codedeploy"

			tags := createTagMap(&PipelineTags{
				Type: common.StackTypeBucket,
			})

			err := stackUpserter.UpsertStack(bucketStackName, common.TemplateBucket, nil, bucketParams, tags, "", workflow.cloudFormationRoleArn)
			if err != nil {
				return err
			}

			log.Debugf("Waiting for stack '%s' to complete", bucketStackName)
			stack := stackWaiter.AwaitFinalStatus(bucketStackName)
			if stack == nil {
				return fmt.Errorf("Unable to create stack %s", bucketStackName)
			}
			if strings.HasSuffix(stack.Status, "ROLLBACK_COMPLETE") || !strings.HasSuffix(stack.Status, "_COMPLETE") {
				return fmt.Errorf("Ended in failed status %s %s", stack.Status, stack.StatusReason)
			}

			workflow.appRevisionBucket = stack.Outputs["Bucket"]

		}

		return nil
	}
}

func (workflow *serviceWorkflow) serviceRegistryAuthenticator(authenticator common.RepositoryAuthenticator) Executor {
	return func() error {
		log.Debugf("Authenticating to registry '%s'", workflow.serviceImage)
		registryAuth, err := authenticator.AuthenticateRepository(workflow.serviceImage)
		if err != nil {
			return err
		}

		data, err := base64.StdEncoding.DecodeString(registryAuth)
		if err != nil {
			return err
		}

		authParts := strings.Split(string(data), ":")

		workflow.registryAuth = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("{\"username\":\"%s\", \"password\":\"%s\"}", authParts[0], authParts[1])))

		// ImageBuild pull auth
		var authConfigs2 = make(map[string]types.AuthConfig)
		var serviceImagePart = strings.Split(workflow.serviceImage, ":")[0]

		authConfigs2[serviceImagePart] = types.AuthConfig{
			Username:      authParts[0],
			Password:      authParts[1],
			ServerAddress: fmt.Sprintf("https://%s", serviceImagePart),
		}

		workflow.registryAuthConfig = authConfigs2

		return nil
	}
}

func (workflow *serviceWorkflow) connectKubernetes(provider common.KubernetesResourceManagerProvider) Executor {
	return func() error {
		clusterName := workflow.envStack.Name
		kubernetesResourceManager, err := provider.GetResourceManager(clusterName)
		workflow.kubernetesResourceManager = kubernetesResourceManager
		return err
	}
}
<|endoftext|>


<commit_before>// +build !appengine

package fasthttp

import (
	"io"
	"net"
	"net/http"
	"strings"

	"github.com/admpub/fasthttp"
	"github.com/admpub/log"
	"github.com/webx-top/echo/engine"
	"github.com/webx-top/echo/logger"
)

type (
	Response struct {
		context   *fasthttp.RequestCtx
		header    engine.Header
		status    int
		size      int64
		committed bool
		writer    io.Writer
		logger    logger.Logger
	}
)

func NewResponse(c *fasthttp.RequestCtx) *Response {
	return &Response{
		context: c,
		header:  &ResponseHeader{&c.Response.Header},
		writer:  c,
		logger:  log.New("echo"),
	}
}

func (r *Response) Object() interface{} {
	return r.context
}

func (r *Response) Header() engine.Header {
	return r.header
}

func (r *Response) WriteHeader(code int) {
	if r.committed {
		r.logger.Warn("response already committed")
		return
	}
	r.status = code
	r.context.SetStatusCode(code)
	r.committed = true
}

func (r *Response) Write(b []byte) (n int, err error) {
	n, err = r.writer.Write(b)
	r.size += int64(n)
	return
}

func (r *Response) Status() int {
	return r.status
}

func (r *Response) Size() int64 {
	return r.size
}

func (r *Response) Committed() bool {
	return r.committed
}

func (r *Response) SetWriter(w io.Writer) {
	r.writer = w
}

func (r *Response) Writer() io.Writer {
	return r.writer
}

func (r *Response) Hijack(fn func(net.Conn)) {
	r.context.Hijack(fasthttp.HijackHandler(fn))
}

func (r *Response) Body() []byte {
	switch strings.ToLower(r.header.Get(`Content-Encoding`)) {
	case `gzip`:
		body, err := r.context.Response.BodyGunzip()
		if err != nil {
			r.logger.Error(err)
		}
		return body
	case `deflate`:
		body, err := r.context.Response.BodyInflate()
		if err != nil {
			r.logger.Error(err)
		}
		return body
	default:
		return r.context.Response.Body()
	}
}

func (r *Response) Redirect(url string, code int) {
	r.context.Redirect(url, code)
}

func (r *Response) NotFound() {
	r.context.NotFound()
}

func (r *Response) SetCookie(cookie *http.Cookie) {
	r.header.Set("Set-Cookie", cookie.String())
}

func (r *Response) ServeFile(file string) {
	fasthttp.ServeFile(r.context, file)
}

func (r *Response) reset(c *fasthttp.RequestCtx, h engine.Header) {
	r.context = c
	r.header = h
	r.status = http.StatusOK
	r.size = 0
	r.committed = false
	r.writer = c
}
<commit_msg>update<commit_after>// +build !appengine

package fasthttp

import (
	"io"
	"net"
	"net/http"
	"strings"

	"github.com/admpub/fasthttp"
	"github.com/admpub/log"
	"github.com/webx-top/echo/engine"
	"github.com/webx-top/echo/logger"
)

type (
	Response struct {
		context   *fasthttp.RequestCtx
		header    engine.Header
		status    int
		size      int64
		committed bool
		writer    io.Writer
		logger    logger.Logger
	}
)

func NewResponse(c *fasthttp.RequestCtx) *Response {
	return &Response{
		context: c,
		header:  &ResponseHeader{&c.Response.Header},
		writer:  c,
		logger:  log.New("echo"),
	}
}

func (r *Response) Object() interface{} {
	return r.context
}

func (r *Response) Header() engine.Header {
	return r.header
}

func (r *Response) WriteHeader(code int) {
	if r.committed {
		r.logger.Warn("response already committed")
		return
	}
	r.status = code
	r.context.SetStatusCode(code)
	r.committed = true
}

func (r *Response) Write(b []byte) (n int, err error) {
	n, err = r.writer.Write(b)
	r.size += int64(n)
	return
}

func (r *Response) Status() int {
	return r.status
}

func (r *Response) Size() int64 {
	return r.size
}

func (r *Response) Committed() bool {
	return r.committed
}

func (r *Response) SetWriter(w io.Writer) {
	r.writer = w
}

func (r *Response) Writer() io.Writer {
	return r.writer
}

func (r *Response) Hijack(fn func(net.Conn)) {
	r.context.Hijack(fasthttp.HijackHandler(fn))
}

func (r *Response) Body() []byte {
	switch strings.ToLower(r.header.Get(`Content-Encoding`)) {
	case `gzip`:
		body, err := r.context.Response.BodyGunzip()
		if err != nil {
			r.logger.Error(err)
		}
		return body
	case `deflate`:
		body, err := r.context.Response.BodyInflate()
		if err != nil {
			r.logger.Error(err)
		}
		return body
	default:
		return r.context.Response.Body()
	}
}

func (r *Response) Redirect(url string, code int) {
	//r.context.Redirect(url, code)  bug: missing port number
	r.header.Set(`Location`, url)
	r.WriteHeader(code)
}

func (r *Response) NotFound() {
	r.context.NotFound()
}

func (r *Response) SetCookie(cookie *http.Cookie) {
	r.header.Set("Set-Cookie", cookie.String())
}

func (r *Response) ServeFile(file string) {
	fasthttp.ServeFile(r.context, file)
}

func (r *Response) reset(c *fasthttp.RequestCtx, h engine.Header) {
	r.context = c
	r.header = h
	r.status = http.StatusOK
	r.size = 0
	r.committed = false
	r.writer = c
}
<|endoftext|>


<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package license

import (
	"errors"
	"fmt"
	"html/template"
	"net/url"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/admpub/license_gen/lib"
	"github.com/admpub/once"
	"github.com/shirou/gopsutil/v3/cpu"
	"github.com/webx-top/com"
	"github.com/webx-top/echo"
	"golang.org/x/net/publicsuffix"

	"github.com/admpub/nging/v3/application/library/config"
)

type Mode int

const (
	ModeMachineID Mode = iota
	ModeDomain
)

var (
	trackerURL      = `https://www.webx.top/product/script/nging/tracker.js`
	productURL      = `https://www.webx.top/product/detail/nging`
	licenseURL      = `https://www.webx.top/product/license/nging`
	versionURL      = `https://www.webx.top/product/version/nging`
	licenseMode     = ModeMachineID
	licenseData     *lib.LicenseData // 拥有的授权数据
	licenseFileName = `license.key`
	licenseFile     = filepath.Join(echo.Wd(), licenseFileName)
	licenseError    = lib.UnlicensedVersion
	licenseModTime  time.Time
	emptyLicense    = lib.LicenseData{}
	downloadOnce    once.Once
	downloadError   error
	downloadTime    time.Time
	lock4err        sync.RWMutex
	lock4data       sync.RWMutex
	// ErrLicenseNotFound 授权证书不存在
	ErrLicenseNotFound = errors.New(`License does not exist`)
	// SkipLicenseCheck 跳过授权检测
	SkipLicenseCheck = true

	// - 需要验证的数据

	version     string //1.2.3-beta
	packageName string //free
	machineID   string
	domain      string
)

type ServerURL struct {
	Tracker         string //用于统计分析的js地址
	Product         string //该产品的详情介绍页面网址
	License         string //许可证验证和许可证下载API网址
	Version         string //该产品最新版本信息API网址
	LicenseFileName string //许可证文件名称
}

func (s *ServerURL) Apply() {
	if len(s.Tracker) > 0 {
		trackerURL = s.Tracker
	}
	if len(s.Product) > 0 {
		productURL = s.Product
	}
	if len(s.License) > 0 {
		licenseURL = s.License
	}
	if len(s.Version) > 0 {
		versionURL = s.Version
	}
	if len(s.LicenseFileName) > 0 {
		licenseFileName = s.LicenseFileName
		licenseFile = filepath.Join(echo.Wd(), licenseFileName)
	}
}

func SetServerURL(s *ServerURL) {
	if s != nil {
		s.Apply()
	}
}

func SetProductName(name string, domains ...string) {
	domain := `www.webx.top`
	if len(domains) > 0 && len(domains[0]) > 0 {
		domain = domains[0]
	}
	trackerURL = `https://` + domain + `/product/script/` + name + `/tracker.js`
	productURL = `https://` + domain + `/product/detail/` + name
	licenseURL = `https://` + domain + `/product/license/` + name
	versionURL = `https://` + domain + `/product/version/` + name
}

func SetProductDomain(domain string) {
	trackerURL = `https://` + domain + `/script/tracker.js`
	productURL = `https://` + domain + `/`
	licenseURL = `https://` + domain + `/license`
	versionURL = `https://` + domain + `/version`
}

func SetVersion(ver string) {
	version = ver
}

func SetPackage(pkg string) {
	packageName = pkg
}

func Version() string {
	return version
}

func Package() string {
	return packageName
}

func ProductURL() string {
	return productURL
}

func Domain() string {
	return domain
}

func SetDomain(_domain string) {
	if licenseMode != ModeDomain {
		licenseMode = ModeDomain
	}
	domain = _domain
}

func FullDomain() string {
	rootDomain := License().Info.Domain
	if len(rootDomain) == 0 {
		return rootDomain
	}
	rootDomain = strings.Trim(rootDomain, `.`)
	realDomain, _ := publicsuffix.EffectiveTLDPlusOne(rootDomain)
	if rootDomain == realDomain {
		return `www.` + realDomain
	}
	return rootDomain
}

func EqDomain(fullDomain string, rootDomain string) bool {
	return lib.CheckDomain(fullDomain, rootDomain)
}

func LicenseMode() Mode {
	return licenseMode
}

func DownloadTime() time.Time {
	return downloadTime
}

func ProductDetailURL() (url string) {
	url = ProductURL() + `?version=` + Version()
	switch licenseMode {
	case ModeMachineID:
		mid, err := MachineID()
		if err != nil {
			panic(err)
		}
		url += `&machineID=` + mid
	case ModeDomain:
		if len(Domain()) > 0 {
			url += `&domain=` + Domain()
		}
	default:
		panic(fmt.Sprintf(`unsupported license mode: %d`, licenseMode))
	}
	return
}

func TrackerURL() string {
	if trackerURL == `#` {
		return ``
	}
	return trackerURL + `?version=` + Version() + `&package=` + Package() + `&os=` + config.Version.BuildOS + `&arch=` + config.Version.BuildArch
}

func TrackerHTML() template.HTML {
	_trackerURL := TrackerURL()
	if len(_trackerURL) == 0 {
		return template.HTML(``)
	}
	return template.HTML(`<script type="text/javascript" async src="` + _trackerURL + `"></script>`)
}

func FilePath() string {
	return licenseFile
}

func FileName() string {
	return licenseFileName
}

func Error() error {
	lock4err.RLock()
	defer lock4err.RUnlock()
	return licenseError
}

func SetError(err error) {
	lock4err.Lock()
	licenseError = err
	lock4err.Unlock()
}

func License() lib.LicenseData {
	lock4data.RLock()
	defer lock4data.RUnlock()
	if licenseData == nil {
		return emptyLicense
	}
	return *licenseData
}

func SetLicense(data *lib.LicenseData) {
	lock4data.Lock()
	licenseData = data
	lock4data.Unlock()
	switch licenseMode {
	case ModeDomain:
		if len(Domain()) == 0 {
			SetDomain(data.Info.Domain)
		}
	case ModeMachineID:
	}
}

var (
	MachineIDEncode = func(v string) string {
		return com.MakePassword(v, `coscms`, 3, 8, 19)
	}
	LicenseDecode = func(b []byte) ([]byte, string) {
		return b, GetOrLoadPublicKey()
	}
)

// MachineID 生成当前机器的机器码
func MachineID() (string, error) {
	if len(machineID) > 0 {
		return machineID, nil
	}
	addrs, err := lib.MACAddresses(false)
	if err != nil {
		return ``, err
	}
	if len(addrs) < 1 {
		return ``, lib.ErrorMachineID
	}
	cpuInfo, err := cpu.Info()
	if err != nil {
		return ``, err
	}
	var cpuID string
	if len(cpuInfo) > 0 {
		cpuID = cpuInfo[0].PhysicalID
		if len(cpuID) == 0 {
			cpuID = com.Md5(com.Dump(cpuInfo, false))
		}
	}
	machineID = MachineIDEncode(lib.Hash(addrs[0]) + `#` + cpuID)
	return machineID, err
}

// FullLicenseURL 包含完整参数的授权网址
func FullLicenseURL(ctx echo.Context) string {
	return licenseURL + `?` + URLValues(ctx).Encode()
}

// URLValues 组装网址参数
func URLValues(ctx echo.Context) url.Values {
	v := url.Values{}
	v.Set(`os`, config.Version.BuildOS)
	v.Set(`arch`, config.Version.BuildArch)
	v.Set(`sn`, License().Info.LicenseID)
	v.Set(`version`, Version())
	v.Set(`package`, Package())
	if ctx != nil {
		v.Set(`source`, ctx.RequestURI())
	}
	switch licenseMode {
	case ModeMachineID:
		if len(machineID) == 0 {
			var err error
			machineID, err = MachineID()
			if err != nil {
				panic(fmt.Errorf(`failed to get machineID: %v`, err))
			}
		}
		v.Set(`machineID`, machineID)
	case ModeDomain:
		if len(Domain()) == 0 {
			panic(`license domain is required`)
		}
		v.Set(`domain`, Domain())
	default:
		panic(fmt.Sprintf(`unsupported license mode: %d`, licenseMode))
	}
	v.Set(`time`, time.Now().Format(`20060102-150405`))
	return v
}
<commit_msg>update<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package license

import (
	"errors"
	"fmt"
	"html/template"
	"net/url"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/admpub/license_gen/lib"
	"github.com/admpub/once"
	"github.com/shirou/gopsutil/v3/cpu"
	"github.com/webx-top/com"
	"github.com/webx-top/echo"
	"golang.org/x/net/publicsuffix"

	"github.com/admpub/nging/v3/application/library/config"
)

type Mode int

const (
	ModeMachineID Mode = iota
	ModeDomain
)

var (
	trackerURL        = `https://www.webx.top/product/script/nging/tracker.js`
	productURL        = `https://www.webx.top/product/detail/nging`
	licenseURL        = `https://www.webx.top/product/license/nging`
	versionURL        = `https://www.webx.top/product/version/nging`
	licenseMode       = ModeMachineID
	licenseData       *lib.LicenseData // 拥有的授权数据
	licenseFileName   = `license.key`
	licenseFile       = filepath.Join(echo.Wd(), licenseFileName)
	licenseError      = lib.UnlicensedVersion
	licenseModTime    time.Time
	emptyLicense      = lib.LicenseData{}
	downloadOnce      once.Once
	downloadError     error
	downloadTime      time.Time
	lock4err          sync.RWMutex
	lock4data         sync.RWMutex
	onSetLicenseHooks []func(*lib.LicenseData)
	// ErrLicenseNotFound 授权证书不存在
	ErrLicenseNotFound = errors.New(`License does not exist`)
	// SkipLicenseCheck 跳过授权检测
	SkipLicenseCheck = true

	// - 需要验证的数据

	version     string //1.2.3-beta
	packageName string //free
	machineID   string
	domain      string
)

func OnSetLicense(fn func(*lib.LicenseData)) {
	if fn == nil {
		return
	}
	onSetLicenseHooks = append(onSetLicenseHooks, fn)
}

func FireSetLicense(data *lib.LicenseData) {
	for _, fn := range onSetLicenseHooks {
		fn(data)
	}
}

type ServerURL struct {
	Tracker         string //用于统计分析的js地址
	Product         string //该产品的详情介绍页面网址
	License         string //许可证验证和许可证下载API网址
	Version         string //该产品最新版本信息API网址
	LicenseFileName string //许可证文件名称
}

func (s *ServerURL) Apply() {
	if len(s.Tracker) > 0 {
		trackerURL = s.Tracker
	}
	if len(s.Product) > 0 {
		productURL = s.Product
	}
	if len(s.License) > 0 {
		licenseURL = s.License
	}
	if len(s.Version) > 0 {
		versionURL = s.Version
	}
	if len(s.LicenseFileName) > 0 {
		licenseFileName = s.LicenseFileName
		licenseFile = filepath.Join(echo.Wd(), licenseFileName)
	}
}

func SetServerURL(s *ServerURL) {
	if s != nil {
		s.Apply()
	}
}

func SetProductName(name string, domains ...string) {
	domain := `www.webx.top`
	if len(domains) > 0 && len(domains[0]) > 0 {
		domain = domains[0]
	}
	trackerURL = `https://` + domain + `/product/script/` + name + `/tracker.js`
	productURL = `https://` + domain + `/product/detail/` + name
	licenseURL = `https://` + domain + `/product/license/` + name
	versionURL = `https://` + domain + `/product/version/` + name
}

func SetProductDomain(domain string) {
	trackerURL = `https://` + domain + `/script/tracker.js`
	productURL = `https://` + domain + `/`
	licenseURL = `https://` + domain + `/license`
	versionURL = `https://` + domain + `/version`
}

func SetVersion(ver string) {
	version = ver
}

func SetPackage(pkg string) {
	packageName = pkg
}

func Version() string {
	return version
}

func Package() string {
	return packageName
}

func ProductURL() string {
	return productURL
}

func Domain() string {
	return domain
}

func SetDomain(_domain string) {
	if licenseMode != ModeDomain {
		licenseMode = ModeDomain
	}
	domain = _domain
}

func FullDomain() string {
	rootDomain := License().Info.Domain
	if len(rootDomain) == 0 {
		return rootDomain
	}
	rootDomain = strings.Trim(rootDomain, `.`)
	realDomain, _ := publicsuffix.EffectiveTLDPlusOne(rootDomain)
	if rootDomain == realDomain {
		return `www.` + realDomain
	}
	return rootDomain
}

func EqDomain(fullDomain string, rootDomain string) bool {
	return lib.CheckDomain(fullDomain, rootDomain)
}

func LicenseMode() Mode {
	return licenseMode
}

func DownloadTime() time.Time {
	return downloadTime
}

func ProductDetailURL() (url string) {
	url = ProductURL() + `?version=` + Version()
	switch licenseMode {
	case ModeMachineID:
		mid, err := MachineID()
		if err != nil {
			panic(err)
		}
		url += `&machineID=` + mid
	case ModeDomain:
		if len(Domain()) > 0 {
			url += `&domain=` + Domain()
		}
	default:
		panic(fmt.Sprintf(`unsupported license mode: %d`, licenseMode))
	}
	return
}

func TrackerURL() string {
	if trackerURL == `#` {
		return ``
	}
	return trackerURL + `?version=` + Version() + `&package=` + Package() + `&os=` + config.Version.BuildOS + `&arch=` + config.Version.BuildArch
}

func TrackerHTML() template.HTML {
	_trackerURL := TrackerURL()
	if len(_trackerURL) == 0 {
		return template.HTML(``)
	}
	return template.HTML(`<script type="text/javascript" async src="` + _trackerURL + `"></script>`)
}

func FilePath() string {
	return licenseFile
}

func FileName() string {
	return licenseFileName
}

func Error() error {
	lock4err.RLock()
	defer lock4err.RUnlock()
	return licenseError
}

func SetError(err error) {
	lock4err.Lock()
	licenseError = err
	lock4err.Unlock()
}

func License() lib.LicenseData {
	lock4data.RLock()
	defer lock4data.RUnlock()
	if licenseData == nil {
		return emptyLicense
	}
	return *licenseData
}

func SetLicense(data *lib.LicenseData) {
	FireSetLicense(data)
	lock4data.Lock()
	licenseData = data
	lock4data.Unlock()
	switch licenseMode {
	case ModeDomain:
		if len(Domain()) == 0 {
			SetDomain(data.Info.Domain)
		}
	case ModeMachineID:
	}
}

var (
	MachineIDEncode = func(v string) string {
		return com.MakePassword(v, `coscms`, 3, 8, 19)
	}
	LicenseDecode = func(b []byte) ([]byte, string) {
		return b, GetOrLoadPublicKey()
	}
)

// MachineID 生成当前机器的机器码
func MachineID() (string, error) {
	if len(machineID) > 0 {
		return machineID, nil
	}
	addrs, err := lib.MACAddresses(false)
	if err != nil {
		return ``, err
	}
	if len(addrs) < 1 {
		return ``, lib.ErrorMachineID
	}
	cpuInfo, err := cpu.Info()
	if err != nil {
		return ``, err
	}
	var cpuID string
	if len(cpuInfo) > 0 {
		cpuID = cpuInfo[0].PhysicalID
		if len(cpuID) == 0 {
			cpuID = com.Md5(com.Dump(cpuInfo, false))
		}
	}
	machineID = MachineIDEncode(lib.Hash(addrs[0]) + `#` + cpuID)
	return machineID, err
}

// FullLicenseURL 包含完整参数的授权网址
func FullLicenseURL(ctx echo.Context) string {
	return licenseURL + `?` + URLValues(ctx).Encode()
}

// URLValues 组装网址参数
func URLValues(ctx echo.Context) url.Values {
	v := url.Values{}
	v.Set(`os`, config.Version.BuildOS)
	v.Set(`arch`, config.Version.BuildArch)
	v.Set(`sn`, License().Info.LicenseID)
	v.Set(`version`, Version())
	v.Set(`package`, Package())
	if ctx != nil {
		v.Set(`source`, ctx.RequestURI())
	}
	switch licenseMode {
	case ModeMachineID:
		if len(machineID) == 0 {
			var err error
			machineID, err = MachineID()
			if err != nil {
				panic(fmt.Errorf(`failed to get machineID: %v`, err))
			}
		}
		v.Set(`machineID`, machineID)
	case ModeDomain:
		if len(Domain()) == 0 {
			panic(`license domain is required`)
		}
		v.Set(`domain`, Domain())
	default:
		panic(fmt.Sprintf(`unsupported license mode: %d`, licenseMode))
	}
	v.Set(`time`, time.Now().Format(`20060102-150405`))
	return v
}
<|endoftext|>


<commit_before>package terraformer

import (
	"bytes"
	"koding/kites/terraformer/kodingcontext"

	"github.com/hashicorp/terraform/terraform"
	"github.com/koding/kite"
	"github.com/koding/logging"
	"github.com/koding/metrics"
)

var (
	Name    = "terraformer"
	Version = "0.0.1"
)

type Terraformer struct {
	// Log is a specialized log system for terraform
	Log logging.Logger

	// Metrics holds the metric aggregator
	Metrics *metrics.DogStatsD

	// Enable debug mode
	Debug bool

	// Context holds the initial context, all usages should clone it
	Context *kodingcontext.Context
}

type TerraformRequest struct {
	Content   string
	Variables map[string]string
}

func New() *Terraformer {
	return &Terraformer{}
}

func (t *Terraformer) Apply(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	ctx, err := t.context(c, r, false)
	if err != nil {
		return nil, err
	}

	state, err := ctx.Apply()
	if err != nil {
		return nil, err
	}

	return state, nil
}

func (t *Terraformer) Destroy(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	//
	// plan first with destroy option
	//
	plan, err := t.plan(c, r, true)
	if err != nil {
		return nil, err
	}

	//
	// create terraform context options from plan
	//
	copts := c.TerraformContextOptsWithPlan(plan)

	copts.Destroy = true // this is the key point

	// create terraform context with its options
	ctx := terraform.NewContext(copts)

	//
	// apply the change
	//
	state, err := ctx.Apply()
	if err != nil {
		return nil, err
	}

	return state, nil
}

func (t *Terraformer) Plan(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	plan, err := t.plan(c, r, false)
	if err != nil {
		return nil, err
	}

	return plan, nil
}

func (t *Terraformer) context(
	c *kodingcontext.Context,
	r *kite.Request,
	destroy bool,
) (*terraform.Context, error) {
	// get the plan
	plan, err := t.plan(c, r, destroy)
	if err != nil {
		return nil, err
	}

	// create terraform context options from plan
	copts := c.TerraformContextOptsWithPlan(plan)

	// create terraform context with its options
	ctx := terraform.NewContext(copts)

	return ctx, nil
}

func (t *Terraformer) plan(
	c *kodingcontext.Context,
	r *kite.Request,
	destroy bool,
) (*terraform.Plan, error) {
	args := TerraformRequest{}
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	c.Variables = args.Variables

	plan, err := c.Plan(
		bytes.NewBufferString(args.Content),
		destroy,
	)
	if err != nil {
		return nil, err
	}

	return plan, nil
}
<commit_msg>Terrafromer: clean up code<commit_after>package terraformer

import (
	"koding/kites/terraformer/kodingcontext"
	"runtime/debug"
	"strings"

	"github.com/hashicorp/terraform/terraform"
	"github.com/koding/kite"
	"github.com/koding/logging"
	"github.com/koding/metrics"
)

var (
	Name    = "terraformer"
	Version = "0.0.1"
)

type Terraformer struct {
	// Log is a specialized log system for terraform
	Log logging.Logger

	// Metrics holds the metric aggregator
	Metrics *metrics.DogStatsD

	// Enable debug mode
	Debug bool

	// Context holds the initial context, all usages should clone it
	Context *kodingcontext.Context
}

type TerraformRequest struct {
	Content   string
	Variables map[string]string
	Location  string
}

func New() *Terraformer { return &Terraformer{} }

func (t *Terraformer) Plan(r *kite.Request) (plan interface{}, err error) {
	defer func() {
		if err != nil {
			debug.PrintStack()
		}
	}()

	c := t.Context.Clone()
	defer c.Close()

	plan, err = t.plan(c, r, false)
	if err != nil {
		return nil, err
	}

	return plan, nil
}

func (t *Terraformer) Apply(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	ctx, err := t.context(c, r, false)
	if err != nil {
		return nil, err
	}

	return ctx.Apply()
}

func (t *Terraformer) Destroy(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	// plan first with destroy option
	plan, err := t.plan(c, r, true)
	if err != nil {
		return nil, err
	}

	// create terraform context options from plan
	copts := c.TerraformContextOptsWithPlan(plan)

	copts.Destroy = true // this is the key point

	// create terraform context with its options
	ctx := terraform.NewContext(copts)

	//
	// apply the change
	//
	return ctx.Apply()
}

func (t *Terraformer) context(
	c *kodingcontext.Context,
	r *kite.Request,
	destroy bool,
) (*terraform.Context, error) {
	// get the plan
	plan, err := t.plan(c, r, destroy)
	if err != nil {
		return nil, err
	}

	// create terraform context options from plan
	copts := c.TerraformContextOptsWithPlan(plan)

	// create terraform context with its options
	return terraform.NewContext(copts), nil
}

func (t *Terraformer) plan(
	c *kodingcontext.Context,
	r *kite.Request,
	destroy bool,
) (*terraform.Plan, error) {
	args := TerraformRequest{}
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	c.Variables = args.Variables
	c.Location = args.Location

	content := strings.NewReader(args.Content)
	return c.Plan(content, destroy)
}
<|endoftext|>


<commit_before>package sparse

import (
	"github.com/gonum/matrix"
	"github.com/gonum/matrix/mat64"
)

type compressedSparse struct {
	i, j   int
	indptr []int
	ind    []int
	data   []float64
}

func (c *compressedSparse) NNZ() int {
	return len(c.data)
}

func (c *compressedSparse) at(i, j int) float64 {
	if uint(i) < 0 || uint(i) >= uint(c.i) {
		panic(matrix.ErrRowAccess)
	}
	if uint(j) < 0 || uint(j) >= uint(c.j) {
		panic(matrix.ErrColAccess)
	}

	// todo: consider a binary search if we can assume the data is ordered.
	for k := c.indptr[i]; k < c.indptr[i+1]; k++ {
		if c.ind[k] == j {
			return c.data[k]
		}
	}

	return 0
}

type CSR struct {
	compressedSparse
}

func NewCSR(r int, c int, ia []int, ja []int, data []float64) *CSR {
	if uint(r) < 0 {
		panic(matrix.ErrRowAccess)
	}
	if uint(c) < 0 {
		panic(matrix.ErrColAccess)
	}

	return &CSR{
		compressedSparse: compressedSparse{
			i: r, j: c,
			indptr: ia,
			ind:    ja,
			data:   data,
		},
	}
}

func (c *CSR) Dims() (int, int) {
	return c.i, c.j
}

func (c *CSR) At(m, n int) float64 {
	return c.at(m, n)
}

func (c *CSR) T() mat64.Matrix {
	return NewCSC(c.j, c.i, c.indptr, c.ind, c.data)
}

func (c *CSR) ToDense() *mat64.Dense {
	mat := mat64.NewDense(c.i, c.j, nil)

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			mat.Set(i, c.ind[j], c.data[j])
		}
	}

	return mat
}

func (c *CSR) ToDOK() *DOK {
	dok := NewDOK(c.i, c.j)
	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			dok.Set(i, c.ind[j], c.data[j])
		}
	}

	return dok
}

func (c *CSR) ToCOO() *COO {
	rows := make([]int, c.NNZ())

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			rows[j] = i
		}
	}

	coo := NewCOO(c.i, c.j, rows, c.ind, c.data)

	return coo
}

func (c *CSR) ToCSR() *CSR {
	return c
}

func (c *CSR) ToCSC() *CSC {
	return c.ToCOO().ToCSC()
}

func (c *CSR) ToType(matType MatrixType) mat64.Matrix {
	return matType.Convert(c)
}

func (c *CSR) Mul(a, b mat64.Matrix) {
	if dia, ok := a.(*DIA); ok {
		c.mulDIA(dia, b, false)
		return
	}
	if dia, ok := b.(*DIA); ok {
		c.mulDIA(dia, a, true)
		return
	}

	ar, ac := a.Dims()
	br, bc := b.Dims()

	c.indptr = make([]int, ar+1)

	if ac != br {
		panic(matrix.ErrShape)
	}

	c.i, c.j = ar, bc
	t := 0

	lhs, isCsr := a.(*CSR)

	if isCsr {
		for i := 0; i < ar; i++ {
			c.indptr[i] = t
			for j := 0; j < bc; j++ {
				var v float64
				// TODO Consider converting all Sparsers to CSR
				for k := lhs.indptr[i]; k < lhs.indptr[i+1]; k++ {
					v += lhs.data[k] * b.At(lhs.ind[k], j)
				}
				if v != 0 {
					t++
					c.ind = append(c.ind, j)
					c.data = append(c.data, v)
				}
			}
		}
	} else {
		row := make([]float64, ac)
		for i := 0; i < ar; i++ {
			c.indptr[i] = t
			for ci := range row {
				row[ci] = a.At(i, ci)
			}
			for j := 0; j < bc; j++ {
				var v float64
				for ci, e := range row {
					v += e * b.At(ci, j)
				}
				if v != 0 {
					t++
					c.ind = append(c.ind, j)
					c.data = append(c.data, v)
				}
			}
		}
	}

	c.indptr[c.i] = t
}

func (c *CSR) mulDIA(dia *DIA, other mat64.Matrix, trans bool) {
	var csMat compressedSparse
	isCS := false

	if csr, ok := other.(*CSR); ok {
		// TODO consider converting all sparsers to CSR (for RHS operand)
		csMat = csr.compressedSparse
		isCS = true
		c.ind = make([]int, len(csMat.ind))
		c.data = make([]float64, len(csMat.data))
	}

	c.i, c.j = other.Dims()
	c.indptr = make([]int, c.i+1)
	t := 0
	raw := dia.Diagonal()

	for i := 0; i < c.i; i++ {
		c.indptr[i] = t
		var v float64

		if isCS {
			for k := csMat.indptr[i]; k < csMat.indptr[i+1]; k++ {
				var rawval float64
				if trans {
					rawval = raw[csMat.ind[k]]
				} else {
					rawval = raw[i]
				}
				v = csMat.data[k] * rawval
				if v != 0 {
					c.ind[t] = csMat.ind[k]
					c.data[t] = v
					t++
				}
			}
		} else {
			for k := 0; k < c.j; k++ {
				var rawval float64
				if trans {
					rawval = raw[k]
				} else {
					rawval = raw[i]
				}
				v = other.At(i, k) * rawval
				if v != 0 {
					c.ind = append(c.ind, k)
					c.data = append(c.data, v)
					t++
				}
			}
		}
	}

	c.indptr[c.i] = t

	return
}

func (c *CSR) Mul2(a, b mat64.Matrix) {
	ar, ac := a.Dims()
	br, bc := b.Dims()

	c.indptr = make([]int, ar+1)

	if rhs, ok := b.(*DIA); ok {
		c.i, c.j = ar, ac
		var size int
		if lhs, ok := a.(*CSR); ok {
			size = lhs.NNZ()
		} else {
			size = ar * bc
		}
		c.ind = make([]int, size)
		c.data = make([]float64, size)
		t := 0
		raw := rhs.Diagonal()

		for i := 0; i < ar; i++ {
			c.indptr[i] = t
			var v float64
			if lhs, ok := a.(*CSR); ok {
				for k := lhs.indptr[i]; k < lhs.indptr[i+1]; k++ {
					v = lhs.data[k] * raw[i]
					if v != 0 {
						c.ind[t] = k
						c.data[t] = v
						t++
					}
				}

			} else {
				for k := 0; k < ac; k++ {
					v = a.At(i, k) * raw[i]
					if v != 0 {
						c.ind[t] = k
						c.data[t] = v
						t++
					}
				}
			}
		}

		c.indptr[c.i] = t
		c.ind = c.ind[:t]
		c.data = c.data[:t]
		return
	}

	if ac != br {
		panic(matrix.ErrShape)
	}

	c.i, c.j = ar, bc
	c.ind = make([]int, ar*bc)
	c.data = make([]float64, ar*bc)

	t := 0

	for i := 0; i < ar; i++ {
		c.indptr[i] = t
		for j := 0; j < bc; j++ {
			var v float64
			if lhs, ok := a.(*CSR); ok {
				for k := lhs.indptr[i]; k < lhs.indptr[i+1]; k++ {
					v += lhs.data[k] * b.At(lhs.ind[k], j)
				}
				if v != 0 {
					c.ind[t] = j
					c.data[t] = v
					t++
				}
			} else {
				for k := 0; k < ac; k++ {
					v += a.At(i, k) * b.At(k, j)
				}
				if v != 0 {
					c.ind[t] = j
					c.data[t] = v
					t++
				}
				//c.set(i, j, v)
			}
		}
	}
	c.indptr[c.i] = t
	c.ind = c.ind[:t]
	c.data = c.data[:t]
}

func (c *CSR) RowNNZ(i int) int {
	if uint(i) < 0 || uint(i) >= uint(c.i) {
		panic(matrix.ErrRowAccess)
	}
	return c.indptr[i+1] - c.indptr[i]
}

type CSC struct {
	compressedSparse
}

func NewCSC(r int, c int, indptr []int, ind []int, data []float64) *CSC {
	if uint(r) < 0 {
		panic(matrix.ErrRowAccess)
	}
	if uint(c) < 0 {
		panic(matrix.ErrColAccess)
	}

	return &CSC{
		compressedSparse: compressedSparse{
			i: c, j: r,
			indptr: indptr,
			ind:    ind,
			data:   data,
		},
	}
}

func (c *CSC) Dims() (int, int) {
	return c.j, c.i
}

func (c *CSC) At(m, n int) float64 {
	return c.at(n, m)
}

func (c *CSC) T() mat64.Matrix {
	return NewCSR(c.i, c.j, c.indptr, c.ind, c.data)
}

func (c *CSC) ToDense() *mat64.Dense {
	mat := mat64.NewDense(c.j, c.i, nil)

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			mat.Set(c.ind[j], i, c.data[j])
		}
	}

	return mat
}

func (c *CSC) ToDOK() *DOK {
	dok := NewDOK(c.j, c.i)
	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			dok.Set(c.ind[j], i, c.data[j])
		}
	}

	return dok
}

func (c *CSC) ToCOO() *COO {
	cols := make([]int, c.NNZ())

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			cols[j] = i
		}
	}

	coo := NewCOO(c.j, c.i, c.ind, cols, c.data)

	return coo
}

func (c *CSC) ToCSR() *CSR {
	return c.ToCOO().ToCSR()
}

func (c *CSC) ToCSC() *CSC {
	return c
}

func (c *CSC) ToType(matType MatrixType) mat64.Matrix {
	return matType.Convert(c)
}
<commit_msg>added dimension mismatch check for multiplication with a DIA matrix)<commit_after>package sparse

import (
	"github.com/gonum/matrix"
	"github.com/gonum/matrix/mat64"
)

type compressedSparse struct {
	i, j   int
	indptr []int
	ind    []int
	data   []float64
}

func (c *compressedSparse) NNZ() int {
	return len(c.data)
}

func (c *compressedSparse) at(i, j int) float64 {
	if uint(i) < 0 || uint(i) >= uint(c.i) {
		panic(matrix.ErrRowAccess)
	}
	if uint(j) < 0 || uint(j) >= uint(c.j) {
		panic(matrix.ErrColAccess)
	}

	// todo: consider a binary search if we can assume the data is ordered.
	for k := c.indptr[i]; k < c.indptr[i+1]; k++ {
		if c.ind[k] == j {
			return c.data[k]
		}
	}

	return 0
}

type CSR struct {
	compressedSparse
}

func NewCSR(r int, c int, ia []int, ja []int, data []float64) *CSR {
	if uint(r) < 0 {
		panic(matrix.ErrRowAccess)
	}
	if uint(c) < 0 {
		panic(matrix.ErrColAccess)
	}

	return &CSR{
		compressedSparse: compressedSparse{
			i: r, j: c,
			indptr: ia,
			ind:    ja,
			data:   data,
		},
	}
}

func (c *CSR) Dims() (int, int) {
	return c.i, c.j
}

func (c *CSR) At(m, n int) float64 {
	return c.at(m, n)
}

func (c *CSR) T() mat64.Matrix {
	return NewCSC(c.j, c.i, c.indptr, c.ind, c.data)
}

func (c *CSR) ToDense() *mat64.Dense {
	mat := mat64.NewDense(c.i, c.j, nil)

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			mat.Set(i, c.ind[j], c.data[j])
		}
	}

	return mat
}

func (c *CSR) ToDOK() *DOK {
	dok := NewDOK(c.i, c.j)
	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			dok.Set(i, c.ind[j], c.data[j])
		}
	}

	return dok
}

func (c *CSR) ToCOO() *COO {
	rows := make([]int, c.NNZ())

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			rows[j] = i
		}
	}

	coo := NewCOO(c.i, c.j, rows, c.ind, c.data)

	return coo
}

func (c *CSR) ToCSR() *CSR {
	return c
}

func (c *CSR) ToCSC() *CSC {
	return c.ToCOO().ToCSC()
}

func (c *CSR) ToType(matType MatrixType) mat64.Matrix {
	return matType.Convert(c)
}

func (c *CSR) Mul(a, b mat64.Matrix) {
	ar, ac := a.Dims()
	br, bc := b.Dims()

	if dia, ok := a.(*DIA); ok {
		if ac != br {
			panic(matrix.ErrShape)
		}
		c.mulDIA(dia, b, false)
		return
	}
	if dia, ok := b.(*DIA); ok {
		if bc != ar {
			panic(matrix.ErrShape)
		}
		c.mulDIA(dia, a, true)
		return
	}

	if ac != br {
		panic(matrix.ErrShape)
	}

	c.indptr = make([]int, ar+1)

	c.i, c.j = ar, bc
	t := 0

	lhs, isCsr := a.(*CSR)

	if isCsr {
		for i := 0; i < ar; i++ {
			c.indptr[i] = t
			for j := 0; j < bc; j++ {
				var v float64
				// TODO Consider converting all Sparsers to CSR
				for k := lhs.indptr[i]; k < lhs.indptr[i+1]; k++ {
					v += lhs.data[k] * b.At(lhs.ind[k], j)
				}
				if v != 0 {
					t++
					c.ind = append(c.ind, j)
					c.data = append(c.data, v)
				}
			}
		}
	} else {
		row := make([]float64, ac)
		for i := 0; i < ar; i++ {
			c.indptr[i] = t
			for ci := range row {
				row[ci] = a.At(i, ci)
			}
			for j := 0; j < bc; j++ {
				var v float64
				for ci, e := range row {
					v += e * b.At(ci, j)
				}
				if v != 0 {
					t++
					c.ind = append(c.ind, j)
					c.data = append(c.data, v)
				}
			}
		}
	}

	c.indptr[c.i] = t
}

func (c *CSR) mulDIA(dia *DIA, other mat64.Matrix, trans bool) {
	var csMat compressedSparse
	isCS := false

	if csr, ok := other.(*CSR); ok {
		// TODO consider converting all sparsers to CSR (for RHS operand)
		csMat = csr.compressedSparse
		isCS = true
		c.ind = make([]int, len(csMat.ind))
		c.data = make([]float64, len(csMat.data))
	}

	c.i, c.j = other.Dims()
	c.indptr = make([]int, c.i+1)
	t := 0
	raw := dia.Diagonal()

	for i := 0; i < c.i; i++ {
		c.indptr[i] = t
		var v float64

		if isCS {
			for k := csMat.indptr[i]; k < csMat.indptr[i+1]; k++ {
				var rawval float64
				if trans {
					rawval = raw[csMat.ind[k]]
				} else {
					rawval = raw[i]
				}
				v = csMat.data[k] * rawval
				if v != 0 {
					c.ind[t] = csMat.ind[k]
					c.data[t] = v
					t++
				}
			}
		} else {
			for k := 0; k < c.j; k++ {
				var rawval float64
				if trans {
					rawval = raw[k]
				} else {
					rawval = raw[i]
				}
				v = other.At(i, k) * rawval
				if v != 0 {
					c.ind = append(c.ind, k)
					c.data = append(c.data, v)
					t++
				}
			}
		}
	}

	c.indptr[c.i] = t

	return
}

func (c *CSR) Mul2(a, b mat64.Matrix) {
	ar, ac := a.Dims()
	br, bc := b.Dims()

	c.indptr = make([]int, ar+1)

	if rhs, ok := b.(*DIA); ok {
		c.i, c.j = ar, ac
		var size int
		if lhs, ok := a.(*CSR); ok {
			size = lhs.NNZ()
		} else {
			size = ar * bc
		}
		c.ind = make([]int, size)
		c.data = make([]float64, size)
		t := 0
		raw := rhs.Diagonal()

		for i := 0; i < ar; i++ {
			c.indptr[i] = t
			var v float64
			if lhs, ok := a.(*CSR); ok {
				for k := lhs.indptr[i]; k < lhs.indptr[i+1]; k++ {
					v = lhs.data[k] * raw[i]
					if v != 0 {
						c.ind[t] = k
						c.data[t] = v
						t++
					}
				}

			} else {
				for k := 0; k < ac; k++ {
					v = a.At(i, k) * raw[i]
					if v != 0 {
						c.ind[t] = k
						c.data[t] = v
						t++
					}
				}
			}
		}

		c.indptr[c.i] = t
		c.ind = c.ind[:t]
		c.data = c.data[:t]
		return
	}

	if ac != br {
		panic(matrix.ErrShape)
	}

	c.i, c.j = ar, bc
	c.ind = make([]int, ar*bc)
	c.data = make([]float64, ar*bc)

	t := 0

	for i := 0; i < ar; i++ {
		c.indptr[i] = t
		for j := 0; j < bc; j++ {
			var v float64
			if lhs, ok := a.(*CSR); ok {
				for k := lhs.indptr[i]; k < lhs.indptr[i+1]; k++ {
					v += lhs.data[k] * b.At(lhs.ind[k], j)
				}
				if v != 0 {
					c.ind[t] = j
					c.data[t] = v
					t++
				}
			} else {
				for k := 0; k < ac; k++ {
					v += a.At(i, k) * b.At(k, j)
				}
				if v != 0 {
					c.ind[t] = j
					c.data[t] = v
					t++
				}
				//c.set(i, j, v)
			}
		}
	}
	c.indptr[c.i] = t
	c.ind = c.ind[:t]
	c.data = c.data[:t]
}

func (c *CSR) RowNNZ(i int) int {
	if uint(i) < 0 || uint(i) >= uint(c.i) {
		panic(matrix.ErrRowAccess)
	}
	return c.indptr[i+1] - c.indptr[i]
}

type CSC struct {
	compressedSparse
}

func NewCSC(r int, c int, indptr []int, ind []int, data []float64) *CSC {
	if uint(r) < 0 {
		panic(matrix.ErrRowAccess)
	}
	if uint(c) < 0 {
		panic(matrix.ErrColAccess)
	}

	return &CSC{
		compressedSparse: compressedSparse{
			i: c, j: r,
			indptr: indptr,
			ind:    ind,
			data:   data,
		},
	}
}

func (c *CSC) Dims() (int, int) {
	return c.j, c.i
}

func (c *CSC) At(m, n int) float64 {
	return c.at(n, m)
}

func (c *CSC) T() mat64.Matrix {
	return NewCSR(c.i, c.j, c.indptr, c.ind, c.data)
}

func (c *CSC) ToDense() *mat64.Dense {
	mat := mat64.NewDense(c.j, c.i, nil)

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			mat.Set(c.ind[j], i, c.data[j])
		}
	}

	return mat
}

func (c *CSC) ToDOK() *DOK {
	dok := NewDOK(c.j, c.i)
	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			dok.Set(c.ind[j], i, c.data[j])
		}
	}

	return dok
}

func (c *CSC) ToCOO() *COO {
	cols := make([]int, c.NNZ())

	for i := 0; i < len(c.indptr)-1; i++ {
		for j := c.indptr[i]; j < c.indptr[i+1]; j++ {
			cols[j] = i
		}
	}

	coo := NewCOO(c.j, c.i, c.ind, cols, c.data)

	return coo
}

func (c *CSC) ToCSR() *CSR {
	return c.ToCOO().ToCSR()
}

func (c *CSC) ToCSC() *CSC {
	return c
}

func (c *CSC) ToType(matType MatrixType) mat64.Matrix {
	return matType.Convert(c)
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package html

import (
	"bytes"
	"fmt"
	"json"
	"strings"
	"utf8"
)

// nextJSCtx returns the context that determines whether a slash after the
// given run of tokens tokens starts a regular expression instead of a division
// operator: / or /=.
//
// This assumes that the token run does not include any string tokens, comment
// tokens, regular expression literal tokens, or division operators.
//
// This fails on some valid but nonsensical JavaScript programs like
// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
// fail on any known useful programs. It is based on the draft
// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
// http://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
	s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
	if len(s) == 0 {
		return preceding
	}

	// All cases below are in the single-byte UTF-8 group.
	switch c, n := s[len(s)-1], len(s); c {
	case '+', '-':
		// ++ and -- are not regexp preceders, but + and - are whether
		// they are used as infix or prefix operators.
		start := n - 1
		// Count the number of adjacent dashes or pluses.
		for start > 0 && s[start-1] == c {
			start--
		}
		if (n-start)&1 == 1 {
			// Reached for trailing minus signs since "---" is the
			// same as "-- -".
			return jsCtxRegexp
		}
		return jsCtxDivOp
	case '.':
		// Handle "42."
		if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
			return jsCtxDivOp
		}
		return jsCtxRegexp
	// Suffixes for all punctuators from section 7.7 of the language spec
	// that only end binary operators not handled above.
	case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
		return jsCtxRegexp
	// Suffixes for all punctuators from section 7.7 of the language spec
	// that are prefix operators not handled above.
	case '!', '~':
		return jsCtxRegexp
	// Matches all the punctuators from section 7.7 of the language spec
	// that are open brackets not handled above.
	case '(', '[':
		return jsCtxRegexp
	// Matches all the punctuators from section 7.7 of the language spec
	// that precede expression starts.
	case ':', ';', '{':
		return jsCtxRegexp
	// CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
	// are handled in the default except for '}' which can precede a
	// division op as in
	//    ({ valueOf: function () { return 42 } } / 2
	// which is valid, but, in practice, developers don't divide object
	// literals, so our heuristic works well for code like
	//    function () { ... }  /foo/.test(x) && sideEffect();
	// The ')' punctuator can precede a regular expression as in
	//     if (b) /foo/.test(x) && ...
	// but this is much less likely than
	//     (a + b) / c
	case '}':
		return jsCtxRegexp
	default:
		// Look for an IdentifierName and see if it is a keyword that
		// can precede a regular expression.
		j := n
		for j > 0 && isJSIdentPart(int(s[j-1])) {
			j--
		}
		if regexpPrecederKeywords[string(s[j:])] {
			return jsCtxRegexp
		}
	}
	// Otherwise is a punctuator not listed above, or
	// a string which precedes a div op, or an identifier
	// which precedes a div op.
	return jsCtxDivOp
}

// regexPrecederKeywords is a set of reserved JS keywords that can precede a
// regular expression in JS source.
var regexpPrecederKeywords = map[string]bool{
	"break":      true,
	"case":       true,
	"continue":   true,
	"delete":     true,
	"do":         true,
	"else":       true,
	"finally":    true,
	"in":         true,
	"instanceof": true,
	"return":     true,
	"throw":      true,
	"try":        true,
	"typeof":     true,
	"void":       true,
}

// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
// nether side-effects nor free variables outside (NaN, Infinity).
func jsValEscaper(args ...interface{}) string {
	var a interface{}
	if len(args) == 1 {
		a = args[0]
	} else {
		a = fmt.Sprint(args...)
	}
	// TODO: detect cycles before calling Marshal which loops infinitely on
	// cyclic data. This may be an unnacceptable DoS risk.

	// TODO: make sure that json.Marshal escapes codepoints U+2028 & U+2029
	// so it falls within the subset of JSON which is valid JS and maybe
	// post-process to prevent it from containing
	// "<!--", "-->", "<![CDATA[", "]]>", or "</script"
	// in case custom marshallers produce output containing those.

	// TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.

	// TODO: JSON allows arbitrary unicode codepoints, but EcmaScript
	// defines a SourceCharacter as either a UTF-16 or UCS-2 code-unit.
	// Determine whether supplemental codepoints in UTF-8 encoded JS inside
	// string literals are properly interpreted by major interpreters.

	b, err := json.Marshal(a)
	if err != nil {
		// Put a space before comment so that if it is flush against
		// a division operator it is not turned into a line comment:
		//     x/{{y}}
		// turning into
		//     x//* error marshalling y:
		//          second line of error message */null
		return fmt.Sprintf(" /* %s */null ", strings.Replace(err.String(), "*/", "* /", -1))
	}
	if len(b) != 0 {
		first, _ := utf8.DecodeRune(b)
		last, _ := utf8.DecodeLastRune(b)
		if isJSIdentPart(first) || isJSIdentPart(last) {
			return " " + string(b) + " "
		}
	}
	return string(b)
}

// jsStrEscaper produces a string that can be included between quotes in
// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
// or in an HTML5 event handler attribute such as onclick.
func jsStrEscaper(args ...interface{}) string {
	ok := false
	var s string
	if len(args) == 1 {
		s, ok = args[0].(string)
	}
	if !ok {
		s = fmt.Sprint(args...)
	}
	var b bytes.Buffer
	written := 0
	for i, r := range s {
		var repl string
		switch r {
		case 0:
			repl = `\0`
		case '\t':
			repl = `\t`
		case '\n':
			repl = `\n`
		case '\v':
			// "\v" == "v" on IE 6.
			repl = `\x0b`
		case '\f':
			repl = `\f`
		case '\r':
			repl = `\r`
		// Encode HTML specials as hex so the output can be embedded
		// in HTML attributes without further encoding.
		case '"':
			repl = `\x22`
		case '&':
			repl = `\x26`
		case '\'':
			repl = `\x27`
		case '+':
			repl = `\x2b`
		case '/':
			repl = `\/`
		case '<':
			repl = `\x3c`
		case '>':
			repl = `\x3e`
		case '\\':
			repl = `\\`
		case '\u2028':
			repl = `\u2028`
		case '\u2029':
			repl = `\u2029`
		default:
			continue
		}
		b.WriteString(s[written:i])
		b.WriteString(repl)
		written = i + utf8.RuneLen(r)
	}
	if written == 0 {
		return s
	}
	b.WriteString(s[written:])
	return b.String()
}

// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
// specials so the result is treated literally when included in a regular
// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
// the literal text of {{.X}} followed by the string "bar".
func jsRegexpEscaper(args ...interface{}) string {
	ok := false
	var s string
	if len(args) == 1 {
		s, ok = args[0].(string)
	}
	if !ok {
		s = fmt.Sprint(args...)
	}
	var b bytes.Buffer
	written := 0
	for i, r := range s {
		var repl string
		switch r {
		case 0:
			repl = `\0`
		case '\t':
			repl = `\t`
		case '\n':
			repl = `\n`
		case '\v':
			// "\v" == "v" on IE 6.
			repl = `\x0b`
		case '\f':
			repl = `\f`
		case '\r':
			repl = `\r`
		// Encode HTML specials as hex so the output can be embedded
		// in HTML attributes without further encoding.
		case '"':
			repl = `\x22`
		case '$':
			repl = `\$`
		case '&':
			repl = `\x26`
		case '\'':
			repl = `\x27`
		case '(':
			repl = `\(`
		case ')':
			repl = `\)`
		case '*':
			repl = `\*`
		case '+':
			repl = `\x2b`
		case '-':
			repl = `\-`
		case '.':
			repl = `\.`
		case '/':
			repl = `\/`
		case '<':
			repl = `\x3c`
		case '>':
			repl = `\x3e`
		case '?':
			repl = `\?`
		case '[':
			repl = `\[`
		case '\\':
			repl = `\\`
		case ']':
			repl = `\]`
		case '^':
			repl = `\^`
		case '{':
			repl = `\{`
		case '|':
			repl = `\|`
		case '}':
			repl = `\}`
		case '\u2028':
			repl = `\u2028`
		case '\u2029':
			repl = `\u2029`
		default:
			continue
		}
		b.WriteString(s[written:i])
		b.WriteString(repl)
		written = i + utf8.RuneLen(r)
	}
	if written == 0 {
		return s
	}
	b.WriteString(s[written:])
	return b.String()
}

// isJSIdentPart is true if the given rune is a JS identifier part.
// It does not handle all the non-Latin letters, joiners, and combining marks,
// but it does handle every codepoint that can occur in a numeric literal or
// a keyword.
func isJSIdentPart(rune int) bool {
	switch {
	case '$' == rune:
		return true
	case '0' <= rune && rune <= '9':
		return true
	case 'A' <= rune && rune <= 'Z':
		return true
	case '_' == rune:
		return true
	case 'a' <= rune && rune <= 'z':
		return true
	}
	return false
}
<commit_msg>exp/template/html: string replacement refactoring.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package html

import (
	"bytes"
	"fmt"
	"json"
	"strings"
	"utf8"
)

// nextJSCtx returns the context that determines whether a slash after the
// given run of tokens tokens starts a regular expression instead of a division
// operator: / or /=.
//
// This assumes that the token run does not include any string tokens, comment
// tokens, regular expression literal tokens, or division operators.
//
// This fails on some valid but nonsensical JavaScript programs like
// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
// fail on any known useful programs. It is based on the draft
// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
// http://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
	s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
	if len(s) == 0 {
		return preceding
	}

	// All cases below are in the single-byte UTF-8 group.
	switch c, n := s[len(s)-1], len(s); c {
	case '+', '-':
		// ++ and -- are not regexp preceders, but + and - are whether
		// they are used as infix or prefix operators.
		start := n - 1
		// Count the number of adjacent dashes or pluses.
		for start > 0 && s[start-1] == c {
			start--
		}
		if (n-start)&1 == 1 {
			// Reached for trailing minus signs since "---" is the
			// same as "-- -".
			return jsCtxRegexp
		}
		return jsCtxDivOp
	case '.':
		// Handle "42."
		if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
			return jsCtxDivOp
		}
		return jsCtxRegexp
	// Suffixes for all punctuators from section 7.7 of the language spec
	// that only end binary operators not handled above.
	case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
		return jsCtxRegexp
	// Suffixes for all punctuators from section 7.7 of the language spec
	// that are prefix operators not handled above.
	case '!', '~':
		return jsCtxRegexp
	// Matches all the punctuators from section 7.7 of the language spec
	// that are open brackets not handled above.
	case '(', '[':
		return jsCtxRegexp
	// Matches all the punctuators from section 7.7 of the language spec
	// that precede expression starts.
	case ':', ';', '{':
		return jsCtxRegexp
	// CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
	// are handled in the default except for '}' which can precede a
	// division op as in
	//    ({ valueOf: function () { return 42 } } / 2
	// which is valid, but, in practice, developers don't divide object
	// literals, so our heuristic works well for code like
	//    function () { ... }  /foo/.test(x) && sideEffect();
	// The ')' punctuator can precede a regular expression as in
	//     if (b) /foo/.test(x) && ...
	// but this is much less likely than
	//     (a + b) / c
	case '}':
		return jsCtxRegexp
	default:
		// Look for an IdentifierName and see if it is a keyword that
		// can precede a regular expression.
		j := n
		for j > 0 && isJSIdentPart(int(s[j-1])) {
			j--
		}
		if regexpPrecederKeywords[string(s[j:])] {
			return jsCtxRegexp
		}
	}
	// Otherwise is a punctuator not listed above, or
	// a string which precedes a div op, or an identifier
	// which precedes a div op.
	return jsCtxDivOp
}

// regexPrecederKeywords is a set of reserved JS keywords that can precede a
// regular expression in JS source.
var regexpPrecederKeywords = map[string]bool{
	"break":      true,
	"case":       true,
	"continue":   true,
	"delete":     true,
	"do":         true,
	"else":       true,
	"finally":    true,
	"in":         true,
	"instanceof": true,
	"return":     true,
	"throw":      true,
	"try":        true,
	"typeof":     true,
	"void":       true,
}

// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
// nether side-effects nor free variables outside (NaN, Infinity).
func jsValEscaper(args ...interface{}) string {
	var a interface{}
	if len(args) == 1 {
		a = args[0]
	} else {
		a = fmt.Sprint(args...)
	}
	// TODO: detect cycles before calling Marshal which loops infinitely on
	// cyclic data. This may be an unnacceptable DoS risk.

	// TODO: make sure that json.Marshal escapes codepoints U+2028 & U+2029
	// so it falls within the subset of JSON which is valid JS and maybe
	// post-process to prevent it from containing
	// "<!--", "-->", "<![CDATA[", "]]>", or "</script"
	// in case custom marshallers produce output containing those.

	// TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.

	// TODO: JSON allows arbitrary unicode codepoints, but EcmaScript
	// defines a SourceCharacter as either a UTF-16 or UCS-2 code-unit.
	// Determine whether supplemental codepoints in UTF-8 encoded JS inside
	// string literals are properly interpreted by major interpreters.

	b, err := json.Marshal(a)
	if err != nil {
		// Put a space before comment so that if it is flush against
		// a division operator it is not turned into a line comment:
		//     x/{{y}}
		// turning into
		//     x//* error marshalling y:
		//          second line of error message */null
		return fmt.Sprintf(" /* %s */null ", strings.Replace(err.String(), "*/", "* /", -1))
	}
	if len(b) != 0 {
		first, _ := utf8.DecodeRune(b)
		last, _ := utf8.DecodeLastRune(b)
		if isJSIdentPart(first) || isJSIdentPart(last) {
			return " " + string(b) + " "
		}
	}
	return string(b)
}

// jsStrEscaper produces a string that can be included between quotes in
// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
// or in an HTML5 event handler attribute such as onclick.
func jsStrEscaper(args ...interface{}) string {
	return replace(stringify(args...), jsStrReplacementTable)
}

// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
// specials so the result is treated literally when included in a regular
// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
// the literal text of {{.X}} followed by the string "bar".
func jsRegexpEscaper(args ...interface{}) string {
	return replace(stringify(args...), jsRegexpReplacementTable)
}

// stringify is an optimized form of fmt.Sprint.
func stringify(args ...interface{}) string {
	if len(args) == 1 {
		if s, ok := args[0].(string); ok {
			return s
		}
	}
	return fmt.Sprint(args...)
}

// replace replaces each rune r of s with replacementTable[r], provided that
// r < len(replacementTable). If replacementTable[r] is the empty string then
// no replacement is made.
// It also replaces the runes '\u2028' and '\u2029' with the strings
// `\u2028` and `\u2029`. Note the different quotes used.
func replace(s string, replacementTable []string) string {
	var b bytes.Buffer
	written := 0
	for i, r := range s {
		var repl string
		switch {
		case r < len(replacementTable) && replacementTable[r] != "":
			repl = replacementTable[r]
		case r == '\u2028':
			repl = `\u2028`
		case r == '\u2029':
			repl = `\u2029`
		default:
			continue
		}
		b.WriteString(s[written:i])
		b.WriteString(repl)
		written = i + utf8.RuneLen(r)
	}
	if written == 0 {
		return s
	}
	b.WriteString(s[written:])
	return b.String()
}

var jsStrReplacementTable = []string{
	0:    `\0`,
	'\t': `\t`,
	'\n': `\n`,
	'\v': `\x0b`, // "\v" == "v" on IE 6.
	'\f': `\f`,
	'\r': `\r`,
	// Encode HTML specials as hex so the output can be embedded
	// in HTML attributes without further encoding.
	'"':  `\x22`,
	'&':  `\x26`,
	'\'': `\x27`,
	'+':  `\x2b`,
	'/':  `\/`,
	'<':  `\x3c`,
	'>':  `\x3e`,
	'\\': `\\`,
}

var jsRegexpReplacementTable = []string{
	0:    `\0`,
	'\t': `\t`,
	'\n': `\n`,
	'\v': `\x0b`, // "\v" == "v" on IE 6.
	'\f': `\f`,
	'\r': `\r`,
	// Encode HTML specials as hex so the output can be embedded
	// in HTML attributes without further encoding.
	'"':  `\x22`,
	'$':  `\$`,
	'&':  `\x26`,
	'\'': `\x27`,
	'(':  `\(`,
	')':  `\)`,
	'*':  `\*`,
	'+':  `\x2b`,
	'-':  `\-`,
	'.':  `\.`,
	'/':  `\/`,
	'<':  `\x3c`,
	'>':  `\x3e`,
	'?':  `\?`,
	'[':  `\[`,
	'\\': `\\`,
	']':  `\]`,
	'^':  `\^`,
	'{':  `\{`,
	'|':  `\|`,
	'}':  `\}`,
}

// isJSIdentPart is true if the given rune is a JS identifier part.
// It does not handle all the non-Latin letters, joiners, and combining marks,
// but it does handle every codepoint that can occur in a numeric literal or
// a keyword.
func isJSIdentPart(rune int) bool {
	switch {
	case '$' == rune:
		return true
	case '0' <= rune && rune <= '9':
		return true
	case 'A' <= rune && rune <= 'Z':
		return true
	case '_' == rune:
		return true
	case 'a' <= rune && rune <= 'z':
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

func main() {
	foo(43)
}

func foo(f int) {
	defer func(o, f int) {
		println("defer", o, f)
	}(one(), f+10)
	println("foo")
	f++
	println("end", f)
}

func one() int {
	println("one")
	return 1
}
<commit_msg>remove defer<commit_after><|endoftext|>


<commit_before><commit_msg>lint pfs-volume-driver<commit_after><|endoftext|>


<commit_before>package tests_test

import (
	"fmt"

	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	v1network "k8s.io/api/networking/v1"
	v13 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tests"
	cd "kubevirt.io/kubevirt/tests/containerdisk"
)

func assertPingSucceed(ip string, vmi *v1.VirtualMachineInstance) {
	expecter, err := tests.LoggedInCirrosExpecter(vmi)
	Expect(err).ToNot(HaveOccurred())
	defer expecter.Close()

	err = tests.CheckForTextExpecter(vmi, []expect.Batcher{
		&expect.BSnd{S: fmt.Sprintf("ping -w 3 %s \n", ip)},
		&expect.BExp{R: "0% packet loss"},
	}, 60)
	Expect(err).ToNot(HaveOccurred())
}

func assertPingFail(ip string, vmi *v1.VirtualMachineInstance) {
	expecter, err := tests.LoggedInCirrosExpecter(vmi)
	Expect(err).ToNot(HaveOccurred())
	defer expecter.Close()

	err = tests.CheckForTextExpecter(vmi, []expect.Batcher{
		&expect.BSnd{S: fmt.Sprintf("ping -w 3 %s \n", ip)},
		&expect.BExp{R: "100% packet loss"},
	}, 60)
	Expect(err).ToNot(HaveOccurred())
}

var _ = Describe("[rfe_id:150][crit:high][vendor:cnv-qe@redhat.com][level:component]Networkpolicy", func() {

	var virtClient kubecli.KubevirtClient

	var vmia *v1.VirtualMachineInstance
	var vmib *v1.VirtualMachineInstance
	var vmic *v1.VirtualMachineInstance

	tests.BeforeAll(func() {
		var err error

		virtClient, err = kubecli.GetKubevirtClient()
		tests.PanicOnError(err)

		tests.SkipIfUseFlannel(virtClient)
		tests.BeforeTestCleanup()
		// Create three vmis, vmia and vmib are in same namespace, vmic is in different namespace
		vmia = tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
		vmia.Labels = map[string]string{"type": "test"}
		vmia, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmia)
		Expect(err).ToNot(HaveOccurred())

		vmib = tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
		_, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmib)
		Expect(err).ToNot(HaveOccurred())

		vmic = tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
		vmic.Namespace = tests.NamespaceTestAlternative
		_, err = virtClient.VirtualMachineInstance(tests.NamespaceTestAlternative).Create(vmic)
		Expect(err).ToNot(HaveOccurred())

		tests.WaitForSuccessfulVMIStart(vmia)
		tests.WaitForSuccessfulVMIStart(vmib)
		tests.WaitForSuccessfulVMIStart(vmic)

		vmia, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmia.Name, &v13.GetOptions{})
		Expect(err).ToNot(HaveOccurred())
		vmib, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmib.Name, &v13.GetOptions{})
		Expect(err).ToNot(HaveOccurred())
		vmic, err = virtClient.VirtualMachineInstance(tests.NamespaceTestAlternative).Get(vmic.Name, &v13.GetOptions{})
		Expect(err).ToNot(HaveOccurred())

	})

	Context("vms limited by Default-deny networkpolicy", func() {

		BeforeEach(func() {
			// deny-by-default networkpolicy will deny all the traffice to the vms in the namespace
			By("Create deny-by-default networkpolicy")
			networkpolicy := &v1network.NetworkPolicy{
				ObjectMeta: v13.ObjectMeta{
					Name: "deny-by-default",
				},
				Spec: v1network.NetworkPolicySpec{
					PodSelector: v13.LabelSelector{},
					Ingress:     []v1network.NetworkPolicyIngressRule{},
				},
			}
			_, err := virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Create(networkpolicy)
			Expect(err).ToNot(HaveOccurred())
		})

		It("[test_id:1511] should be failed to reach vmia from vmib", func() {
			By("Connect vmia from vmib")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmib)
		})

		It("[test_id:1512] should be failed to reach vmib from vmia", func() {
			By("Connect vmib from vmia")
			ip := vmib.Status.Interfaces[0].IP
			assertPingFail(ip, vmia)
		})

		AfterEach(func() {
			Expect(virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Delete("deny-by-default", &v13.DeleteOptions{})).To(Succeed())
		})

	})

	Context("vms limited by allow same namespace networkpolicy", func() {
		BeforeEach(func() {
			// allow-same-namespave networkpolicy will only allow the traffice inside the namespace
			By("Create allow-same-namespace networkpolicy")
			networkpolicy := &v1network.NetworkPolicy{
				ObjectMeta: v13.ObjectMeta{
					Name: "allow-same-namespace",
				},
				Spec: v1network.NetworkPolicySpec{
					PodSelector: v13.LabelSelector{},
					Ingress: []v1network.NetworkPolicyIngressRule{
						{
							From: []v1network.NetworkPolicyPeer{
								{
									PodSelector: &v13.LabelSelector{},
								},
							},
						},
					},
				},
			}
			_, err := virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Create(networkpolicy)
			Expect(err).ToNot(HaveOccurred())
		})

		It("[test_id:1513] should be successful to reach vmia from vmib", func() {
			By("Connect vmia from vmib in same namespace")
			ip := vmia.Status.Interfaces[0].IP
			assertPingSucceed(ip, vmib)
		})

		It("[test_id:1514] should be failed to reach vmia from vmic", func() {
			By("Connect vmia from vmic in differnet namespace")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmic)
		})

		AfterEach(func() {
			Expect(virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Delete("allow-same-namespace", &v13.DeleteOptions{})).To(Succeed())
		})

	})

	Context("vms limited by deny by label networkpolicy", func() {
		BeforeEach(func() {
			// deny-by-label networkpolicy will deny the traffice for the vm which have the same label
			By("Create deny-by-label networkpolicy")
			networkpolicy := &v1network.NetworkPolicy{
				ObjectMeta: v13.ObjectMeta{
					Name: "deny-by-label",
				},
				Spec: v1network.NetworkPolicySpec{
					PodSelector: v13.LabelSelector{
						MatchLabels: map[string]string{
							"type": "test",
						},
					},
					Ingress: []v1network.NetworkPolicyIngressRule{},
				},
			}
			_, err := virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Create(networkpolicy)
			Expect(err).ToNot(HaveOccurred())
		})

		It("[test_id:1515] should be failed to reach vmia from vmic", func() {
			By("Connect vmia from vmic")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmic)
		})

		It("[test_id:1516] should be failed to reach vmia from vmib", func() {
			By("Connect vmia from vmib")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmib)
		})

		It("[test_id:1517] should be successful to reach vmib from vmic", func() {
			By("Connect vmib from vmic")
			ip := vmib.Status.Interfaces[0].IP
			assertPingSucceed(ip, vmic)
		})

		AfterEach(func() {
			Expect(virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Delete("deny-by-label", &v13.DeleteOptions{})).To(Succeed())
		})

	})

})
<commit_msg>tests, Add skipNetworkPolicyRunningOnKindInfra for NetworkPolicy tests<commit_after>package tests_test

import (
	"fmt"

	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	v1network "k8s.io/api/networking/v1"
	v13 "k8s.io/apimachinery/pkg/apis/meta/v1"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/kubecli"
	"kubevirt.io/kubevirt/tests"
	cd "kubevirt.io/kubevirt/tests/containerdisk"
)

func assertPingSucceed(ip string, vmi *v1.VirtualMachineInstance) {
	expecter, err := tests.LoggedInCirrosExpecter(vmi)
	Expect(err).ToNot(HaveOccurred())
	defer expecter.Close()

	err = tests.CheckForTextExpecter(vmi, []expect.Batcher{
		&expect.BSnd{S: fmt.Sprintf("ping -w 3 %s \n", ip)},
		&expect.BExp{R: "0% packet loss"},
	}, 60)
	Expect(err).ToNot(HaveOccurred())
}

func assertPingFail(ip string, vmi *v1.VirtualMachineInstance) {
	expecter, err := tests.LoggedInCirrosExpecter(vmi)
	Expect(err).ToNot(HaveOccurred())
	defer expecter.Close()

	err = tests.CheckForTextExpecter(vmi, []expect.Batcher{
		&expect.BSnd{S: fmt.Sprintf("ping -w 3 %s \n", ip)},
		&expect.BExp{R: "100% packet loss"},
	}, 60)
	Expect(err).ToNot(HaveOccurred())
}

var _ = Describe("[rfe_id:150][crit:high][vendor:cnv-qe@redhat.com][level:component]Networkpolicy", func() {

	var virtClient kubecli.KubevirtClient

	var vmia *v1.VirtualMachineInstance
	var vmib *v1.VirtualMachineInstance
	var vmic *v1.VirtualMachineInstance

	tests.BeforeAll(func() {
		var err error

		virtClient, err = kubecli.GetKubevirtClient()
		tests.PanicOnError(err)

		tests.SkipIfUseFlannel(virtClient)
		skipNetworkPolicyRunningOnKindInfra()
		tests.BeforeTestCleanup()
		// Create three vmis, vmia and vmib are in same namespace, vmic is in different namespace
		vmia = tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
		vmia.Labels = map[string]string{"type": "test"}
		vmia, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmia)
		Expect(err).ToNot(HaveOccurred())

		vmib = tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
		_, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmib)
		Expect(err).ToNot(HaveOccurred())

		vmic = tests.NewRandomVMIWithEphemeralDiskAndUserdata(cd.ContainerDiskFor(cd.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
		vmic.Namespace = tests.NamespaceTestAlternative
		_, err = virtClient.VirtualMachineInstance(tests.NamespaceTestAlternative).Create(vmic)
		Expect(err).ToNot(HaveOccurred())

		tests.WaitForSuccessfulVMIStart(vmia)
		tests.WaitForSuccessfulVMIStart(vmib)
		tests.WaitForSuccessfulVMIStart(vmic)

		vmia, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmia.Name, &v13.GetOptions{})
		Expect(err).ToNot(HaveOccurred())
		vmib, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmib.Name, &v13.GetOptions{})
		Expect(err).ToNot(HaveOccurred())
		vmic, err = virtClient.VirtualMachineInstance(tests.NamespaceTestAlternative).Get(vmic.Name, &v13.GetOptions{})
		Expect(err).ToNot(HaveOccurred())

	})

	Context("vms limited by Default-deny networkpolicy", func() {

		BeforeEach(func() {
			// deny-by-default networkpolicy will deny all the traffice to the vms in the namespace
			By("Create deny-by-default networkpolicy")
			networkpolicy := &v1network.NetworkPolicy{
				ObjectMeta: v13.ObjectMeta{
					Name: "deny-by-default",
				},
				Spec: v1network.NetworkPolicySpec{
					PodSelector: v13.LabelSelector{},
					Ingress:     []v1network.NetworkPolicyIngressRule{},
				},
			}
			_, err := virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Create(networkpolicy)
			Expect(err).ToNot(HaveOccurred())
		})

		It("[test_id:1511] should be failed to reach vmia from vmib", func() {
			By("Connect vmia from vmib")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmib)
		})

		It("[test_id:1512] should be failed to reach vmib from vmia", func() {
			By("Connect vmib from vmia")
			ip := vmib.Status.Interfaces[0].IP
			assertPingFail(ip, vmia)
		})

		AfterEach(func() {
			Expect(virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Delete("deny-by-default", &v13.DeleteOptions{})).To(Succeed())
		})

	})

	Context("vms limited by allow same namespace networkpolicy", func() {
		BeforeEach(func() {
			// allow-same-namespave networkpolicy will only allow the traffice inside the namespace
			By("Create allow-same-namespace networkpolicy")
			networkpolicy := &v1network.NetworkPolicy{
				ObjectMeta: v13.ObjectMeta{
					Name: "allow-same-namespace",
				},
				Spec: v1network.NetworkPolicySpec{
					PodSelector: v13.LabelSelector{},
					Ingress: []v1network.NetworkPolicyIngressRule{
						{
							From: []v1network.NetworkPolicyPeer{
								{
									PodSelector: &v13.LabelSelector{},
								},
							},
						},
					},
				},
			}
			_, err := virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Create(networkpolicy)
			Expect(err).ToNot(HaveOccurred())
		})

		It("[test_id:1513] should be successful to reach vmia from vmib", func() {
			By("Connect vmia from vmib in same namespace")
			ip := vmia.Status.Interfaces[0].IP
			assertPingSucceed(ip, vmib)
		})

		It("[test_id:1514] should be failed to reach vmia from vmic", func() {
			By("Connect vmia from vmic in differnet namespace")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmic)
		})

		AfterEach(func() {
			Expect(virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Delete("allow-same-namespace", &v13.DeleteOptions{})).To(Succeed())
		})

	})

	Context("vms limited by deny by label networkpolicy", func() {
		BeforeEach(func() {
			// deny-by-label networkpolicy will deny the traffice for the vm which have the same label
			By("Create deny-by-label networkpolicy")
			networkpolicy := &v1network.NetworkPolicy{
				ObjectMeta: v13.ObjectMeta{
					Name: "deny-by-label",
				},
				Spec: v1network.NetworkPolicySpec{
					PodSelector: v13.LabelSelector{
						MatchLabels: map[string]string{
							"type": "test",
						},
					},
					Ingress: []v1network.NetworkPolicyIngressRule{},
				},
			}
			_, err := virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Create(networkpolicy)
			Expect(err).ToNot(HaveOccurred())
		})

		It("[test_id:1515] should be failed to reach vmia from vmic", func() {
			By("Connect vmia from vmic")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmic)
		})

		It("[test_id:1516] should be failed to reach vmia from vmib", func() {
			By("Connect vmia from vmib")
			ip := vmia.Status.Interfaces[0].IP
			assertPingFail(ip, vmib)
		})

		It("[test_id:1517] should be successful to reach vmib from vmic", func() {
			By("Connect vmib from vmic")
			ip := vmib.Status.Interfaces[0].IP
			assertPingSucceed(ip, vmic)
		})

		AfterEach(func() {
			Expect(virtClient.NetworkingV1().NetworkPolicies(vmia.Namespace).Delete("deny-by-label", &v13.DeleteOptions{})).To(Succeed())
		})

	})

})

func skipNetworkPolicyRunningOnKindInfra() {
	if tests.IsRunningOnKindInfra() {
		Skip("Skip Network Policy tests till issue https://github.com/kubevirt/kubevirt/issues/4081 is fixed")
	}
}
<|endoftext|>


<commit_before>package logging

import (
	"testing"
)

func TestLog(t *testing.T) {
	//t.Skipf("skipping...")

	//Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
	var log = ContextLogger

	log.Debug("Useful debugging information.")
	log.Info("Something noteworthy happened!")
	log.Warn("You should probably take a look at this.")
	log.Error("Something failed but I'm not quitting.")
	// Calls panic() after logging
	//log.Panic("I'm bailing.")
	// Calls os.Exit(1) after logging
	//log.Fatal("Bye.")
}
<commit_msg>fix logger test<commit_after>package logging

import (
	"testing"
)

func TestLog(t *testing.T) {
	//t.Skipf("skipping...")

	//Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
	var log = Logger()

	log.Debug("Useful debugging information.")
	log.Info("Something noteworthy happened!")
	log.Warn("You should probably take a look at this.")
	log.Error("Something failed but I'm not quitting.")
	// Calls panic() after logging
	//log.Panic("I'm bailing.")
	// Calls os.Exit(1) after logging
	//log.Fatal("Bye.")
}
<|endoftext|>