Example #1
0
func TestBuildTemplates(t *testing.T) {
	tests := map[string]struct {
		templateName string
		namespace    string
		parms        map[string]string
	}{
		"simple": {
			templateName: "first-stored-template",
			namespace:    "default",
			parms:        map[string]string{},
		},
	}

	for n, c := range tests {
		appCfg := AppConfig{}
		appCfg.Out = &bytes.Buffer{}
		appCfg.refBuilder = &app.ReferenceBuilder{}
		appCfg.SetOpenShiftClient(&client.Fake{}, c.namespace)
		appCfg.KubeClient = ktestclient.NewSimpleFake()
		appCfg.templateSearcher = fakeTemplateSearcher()
		appCfg.AddArguments([]string{c.templateName})
		appCfg.TemplateParameters = []string{}
		for k, v := range c.parms {
			appCfg.TemplateParameters = append(appCfg.TemplateParameters, fmt.Sprintf("%v=%v", k, v))
		}

		components, _, _, parms, err := appCfg.validate()
		if err != nil {
			t.Errorf("%s: Unexpected error: %v", n, err)
		}
		err = appCfg.resolve(components)
		if err != nil {
			t.Errorf("%s: Unexpected error: %v", n, err)
		}
		_, err = appCfg.buildTemplates(components, app.Environment(parms))
		if err != nil {
			t.Errorf("%s: Unexpected error: %v", n, err)
		}
		for _, component := range components {
			match := component.Input().ResolvedMatch
			if !match.IsTemplate() {
				t.Errorf("%s: Expected template match, got: %v", n, match)
			}
			if c.templateName != match.Name {
				t.Errorf("%s: Expected template name %q, got: %q", n, c.templateName, match.Name)
			}
			if len(parms) != len(c.parms) {
				t.Errorf("%s: Template parameters don't match. Expected: %v, Got: %v", n, c.parms, parms)
			}
			for p, v := range parms {
				if c.parms[p] != v {
					t.Errorf("%s: Template parameters don't match. Expected: %v, Got: %v", n, c.parms, parms)
					break
				}
			}
		}
	}
}
Example #2
0
// run executes the provided config applying provided acceptors.
func (c *AppConfig) run(out, errOut io.Writer, acceptors app.Acceptors) (*AppResult, error) {
	c.ensureDockerSearcher()
	repositories, err := c.individualSourceRepositories()
	if err != nil {
		return nil, err
	}
	err = c.detectSource(repositories)
	if err != nil {
		return nil, err
	}
	components, repositories, environment, parameters, err := c.validate()
	if err != nil {
		return nil, err
	}
	if err := c.resolve(components); err != nil {
		return nil, err
	}

	// Couple source with resolved builder components if possible
	if err := c.ensureHasSource(components.NeedsSource(), repositories.NotUsed()); err != nil {
		return nil, err
	}
	// For source repos that are not yet coupled with a component, create components
	sourceComponents, err := c.componentsForRepos(repositories.NotUsed())
	if err != nil {
		return nil, err
	}
	// resolve the source repo components
	if err := c.resolve(sourceComponents); err != nil {
		return nil, err
	}
	components = append(components, sourceComponents...)

	glog.V(4).Infof("Code %v", repositories)
	glog.V(4).Infof("Components %v", components)

	if len(repositories) == 0 && len(components) == 0 {
		return nil, ErrNoInputs
	}

	if len(c.Name) > 0 {
		if err := c.validateEnforcedName(); err != nil {
			return nil, err
		}
	}

	if len(components.ImageComponentRefs()) > 1 && len(c.Name) > 0 {
		return nil, fmt.Errorf("only one component or source repository can be used when specifying a name")
	}

	pipelines, err := c.buildPipelines(components.ImageComponentRefs(), app.Environment(environment))
	if err != nil {
		return nil, err
	}

	objects := app.Objects{}
	accept := app.NewAcceptFirst()
	warned := make(map[string]struct{})
	for _, p := range pipelines {
		accepted, err := p.Objects(accept, acceptors)
		if err != nil {
			return nil, fmt.Errorf("can't setup %q: %v", p.From, err)
		}
		if p.Image != nil && p.Image.HasEmptyDir {
			if _, ok := warned[p.Image.Name]; !ok {
				fmt.Fprintf(errOut, "NOTICE: Image %q uses an EmptyDir volume. Data in EmptyDir volumes is not persisted across deployments.\n", p.Image.Name)
				warned[p.Image.Name] = struct{}{}
			}
		}
		objects = append(objects, accepted...)
	}

	objects = app.AddServices(objects, false)

	templateObjects, err := c.buildTemplates(components.TemplateComponentRefs(), app.Environment(parameters))
	if err != nil {
		return nil, err
	}
	objects = append(objects, templateObjects...)

	buildNames := []string{}
	for _, obj := range objects {
		switch t := obj.(type) {
		case *buildapi.BuildConfig:
			buildNames = append(buildNames, t.Name)
		}
	}

	name := c.Name
	if len(name) == 0 {
		for _, pipeline := range pipelines {
			if pipeline.Deployment != nil {
				name = pipeline.Deployment.Name
				break
			}
		}
	}

	return &AppResult{
		List:       &kapi.List{Items: objects},
		Name:       name,
		BuildNames: buildNames,
		HasSource:  len(repositories) != 0,
		Namespace:  c.originNamespace,
	}, nil
}
Example #3
0
// run executes the provided config applying provided acceptors.
func (c *AppConfig) run(acceptors app.Acceptors) (*AppResult, error) {
	c.ensureDockerSearcher()
	repositories, err := c.individualSourceRepositories()
	if err != nil {
		return nil, err
	}
	err = c.detectSource(repositories)
	if err != nil {
		return nil, err
	}
	components, repositories, environment, parameters, err := c.validate()
	if err != nil {
		return nil, err
	}

	if err := c.resolve(components); err != nil {
		return nil, err
	}

	components, err = c.inferBuildTypes(components)
	if err != nil {
		return nil, err
	}

	// Couple source with resolved builder components if possible
	if err := c.ensureHasSource(components.NeedsSource(), repositories.NotUsed()); err != nil {
		return nil, err
	}

	// For source repos that are not yet coupled with a component, create components
	sourceComponents, err := c.componentsForRepos(repositories.NotUsed())
	if err != nil {
		return nil, err
	}

	// resolve the source repo components
	if err := c.resolve(sourceComponents); err != nil {
		return nil, err
	}
	components = append(components, sourceComponents...)

	glog.V(4).Infof("Code [%v]", repositories)
	glog.V(4).Infof("Components [%v]", components)

	if len(repositories) == 0 && len(components) == 0 {
		return nil, ErrNoInputs
	}

	if len(c.Name) > 0 {
		if err := validateEnforcedName(c.Name); err != nil {
			return nil, err
		}
	}

	if len(c.To) > 0 {
		if err := validateOutputImageReference(c.To); err != nil {
			return nil, err
		}
	}

	imageRefs := components.ImageComponentRefs()
	if len(imageRefs) > 1 && len(c.Name) > 0 {
		return nil, fmt.Errorf("only one component or source repository can be used when specifying a name")
	}
	if len(imageRefs) > 1 && len(c.To) > 0 {
		return nil, fmt.Errorf("only one component or source repository can be used when specifying an output image reference")
	}

	env := app.Environment(environment)

	// identify if there are installable components in the input provided by the user
	installables, name, err := c.installComponents(components, env)
	if err != nil {
		return nil, err
	}
	if len(installables) > 0 {
		return &AppResult{
			List:      &kapi.List{Items: installables},
			Name:      name,
			Namespace: c.originNamespace,

			GeneratedJobs: true,
		}, nil
	}

	pipelines, err := c.buildPipelines(imageRefs, env)
	if err != nil {
		if err == app.ErrNameRequired {
			return nil, fmt.Errorf("can't suggest a valid name, please specify a name with --name")
		}
		if err, ok := err.(app.CircularOutputReferenceError); ok {
			return nil, fmt.Errorf("%v, please specify a different output reference with --to", err)
		}
		return nil, err
	}

	objects := app.Objects{}
	accept := app.NewAcceptFirst()
	for _, p := range pipelines {
		accepted, err := p.Objects(accept, acceptors)
		if err != nil {
			return nil, fmt.Errorf("can't setup %q: %v", p.From, err)
		}
		objects = append(objects, accepted...)
	}

	objects = app.AddServices(objects, false)

	templateObjects, err := c.buildTemplates(components.TemplateComponentRefs(), app.Environment(parameters))
	if err != nil {
		return nil, err
	}
	objects = append(objects, templateObjects...)

	name = c.Name
	if len(name) == 0 {
		for _, pipeline := range pipelines {
			if pipeline.Deployment != nil {
				name = pipeline.Deployment.Name
				break
			}
		}
	}
	if len(name) == 0 {
		for _, obj := range objects {
			if bc, ok := obj.(*buildapi.BuildConfig); ok {
				name = bc.Name
				break
			}
		}
	}

	return &AppResult{
		List:      &kapi.List{Items: objects},
		Name:      name,
		HasSource: len(repositories) != 0,
		Namespace: c.originNamespace,
	}, nil
}
Example #4
0
// Run executes the provided config to generate objects.
func (c *AppConfig) Run() (*AppResult, error) {
	environment, parameters, err := c.validate()
	if err != nil {
		return nil, err
	}
	// TODO: I don't belong here
	c.ensureDockerSearch()

	resolved, err := Resolve(&c.Resolvers, &c.ComponentInputs, &c.GenerationInputs)
	if err != nil {
		return nil, err
	}

	repositories := resolved.Repositories
	components := resolved.Components

	if err := c.validateBuilders(components); err != nil {
		return nil, err
	}

	if len(repositories) == 0 && len(components) == 0 {
		return nil, ErrNoInputs
	}

	if len(c.Name) > 0 {
		if err := validateEnforcedName(c.Name); err != nil {
			return nil, err
		}
	}

	if err := optionallyValidateExposedPorts(c, repositories); err != nil {
		return nil, err
	}

	if len(c.To) > 0 {
		if err := validateOutputImageReference(c.To); err != nil {
			return nil, err
		}
	}

	if len(components.ImageComponentRefs().Group()) > 1 && len(c.Name) > 0 {
		return nil, errors.New("only one component or source repository can be used when specifying a name")
	}
	if len(components.UseSource()) > 1 && len(c.To) > 0 {
		return nil, errors.New("only one component with source can be used when specifying an output image reference")
	}

	env := app.Environment(environment)

	// identify if there are installable components in the input provided by the user
	installables, name, err := c.installComponents(components, env)
	if err != nil {
		return nil, err
	}
	if len(installables) > 0 {
		return &AppResult{
			List:      &kapi.List{Items: installables},
			Name:      name,
			Namespace: c.OriginNamespace,

			GeneratedJobs: true,
		}, nil
	}

	pipelines, err := c.buildPipelines(components.ImageComponentRefs(), env)
	if err != nil {
		if err == app.ErrNameRequired {
			return nil, errors.New("can't suggest a valid name, please specify a name with --name")
		}
		return nil, err
	}

	acceptors := app.Acceptors{app.NewAcceptUnique(c.Typer), app.AcceptNew}
	objects := app.Objects{}
	accept := app.NewAcceptFirst()
	for _, p := range pipelines {
		accepted, err := p.Objects(accept, acceptors)
		if err != nil {
			return nil, fmt.Errorf("can't setup %q: %v", p.From, err)
		}
		objects = append(objects, accepted...)
	}

	objects = app.AddServices(objects, false)

	templateName, templateObjects, err := c.buildTemplates(components.TemplateComponentRefs(), app.Environment(parameters))
	if err != nil {
		return nil, err
	}
	objects = append(objects, templateObjects...)

	name = c.Name
	if len(name) == 0 {
		name = templateName
	}
	if len(name) == 0 {
		for _, pipeline := range pipelines {
			if pipeline.Deployment != nil {
				name = pipeline.Deployment.Name
				break
			}
		}
	}
	if len(name) == 0 {
		for _, obj := range objects {
			if bc, ok := obj.(*buildapi.BuildConfig); ok {
				name = bc.Name
				break
			}
		}
	}

	// Only check circular references for `oc new-build`.
	if c.ExpectToBuild {
		err = c.checkCircularReferences(objects)
		if err != nil {
			if err, ok := err.(app.CircularOutputReferenceError); ok {
				if len(c.To) == 0 {
					// Output reference was generated, return error.
					return nil, fmt.Errorf("%v, set a different tag with --to", err)
				}
				// Output reference was explicitly provided, print warning.
				fmt.Fprintf(c.ErrOut, "--> WARNING: %v\n", err)
			} else {
				return nil, err
			}
		}
	}

	return &AppResult{
		List:      &kapi.List{Items: objects},
		Name:      name,
		HasSource: len(repositories) != 0,
		Namespace: c.OriginNamespace,
	}, nil
}
Example #5
0
// run executes the provided config applying provided acceptors.
func (c *AppConfig) run(acceptors app.Acceptors) (*AppResult, error) {
	c.ensureDockerSearcher()
	repositories, err := c.individualSourceRepositories()
	if err != nil {
		return nil, err
	}
	err = c.detectSource(repositories)
	if err != nil {
		return nil, err
	}
	components, repositories, environment, parameters, err := c.validate()
	if err != nil {
		return nil, err
	}

	if err := c.resolve(components); err != nil {
		return nil, err
	}

	if err := c.inferBuildTypes(components); err != nil {
		return nil, err
	}

	// Couple source with resolved builder components if possible
	if err := c.ensureHasSource(components.NeedsSource(), repositories.NotUsed()); err != nil {
		return nil, err
	}

	// For source repos that are not yet coupled with a component, create components
	sourceComponents, err := c.componentsForRepos(repositories.NotUsed())
	if err != nil {
		return nil, err
	}

	// resolve the source repo components
	if err := c.resolve(sourceComponents); err != nil {
		return nil, err
	}
	components = append(components, sourceComponents...)

	glog.V(4).Infof("Code [%v]", repositories)
	glog.V(4).Infof("Components [%v]", components)

	if len(repositories) == 0 && len(components) == 0 {
		return nil, ErrNoInputs
	}

	if len(c.Name) > 0 {
		if err := c.validateEnforcedName(); err != nil {
			return nil, err
		}
	}

	imageRefs := components.ImageComponentRefs()
	if len(imageRefs) > 1 && len(c.Name) > 0 {
		return nil, fmt.Errorf("only one component or source repository can be used when specifying a name")
	}

	// identify if there are installable components in the input provided by the user
	installables, name, err := c.installComponents(components)
	if err != nil {
		return nil, err
	}
	if len(installables) > 0 {
		return &AppResult{
			List:      &kapi.List{Items: installables},
			Name:      name,
			Namespace: c.originNamespace,

			GeneratedJobs: true,
		}, nil
	}

	pipelines, err := c.buildPipelines(imageRefs, app.Environment(environment))
	if err != nil {
		return nil, err
	}

	objects := app.Objects{}
	accept := app.NewAcceptFirst()
	warned := make(map[string]struct{})
	for _, p := range pipelines {
		accepted, err := p.Objects(accept, acceptors)
		if err != nil {
			return nil, fmt.Errorf("can't setup %q: %v", p.From, err)
		}
		if p.Image != nil && p.Image.HasEmptyDir {
			spec := p.Image.PullSpec()
			if _, ok := warned[spec]; ok {
				fmt.Fprintf(c.ErrOut, "WARNING: Image %q uses an empty directory volume. Data in these volumes is not persisted across deployments.\n", p.Image.Reference.Name)
				warned[spec] = struct{}{}
			}
		}
		objects = append(objects, accepted...)
	}

	objects = app.AddServices(objects, false)

	templateObjects, err := c.buildTemplates(components.TemplateComponentRefs(), app.Environment(parameters))
	if err != nil {
		return nil, err
	}
	objects = append(objects, templateObjects...)

	name = c.Name
	if len(name) == 0 {
		for _, pipeline := range pipelines {
			if pipeline.Deployment != nil {
				name = pipeline.Deployment.Name
				break
			}
		}
	}

	return &AppResult{
		List:      &kapi.List{Items: objects},
		Name:      name,
		HasSource: len(repositories) != 0,
		Namespace: c.originNamespace,
	}, nil
}
Example #6
0
// run executes the provided config applying provided acceptors.
func (c *AppConfig) run(out io.Writer, acceptors app.Acceptors) (*AppResult, error) {
	c.ensureDockerResolver()
	repositories, err := c.individualSourceRepositories()
	if err != nil {
		return nil, err
	}
	err = c.detectSource(repositories)
	if err != nil {
		return nil, err
	}
	components, repositories, environment, parameters, err := c.validate()
	if err != nil {
		return nil, err
	}
	if err := c.resolve(components); err != nil {
		return nil, err
	}

	// Couple source with resolved builder components if possible
	if err := c.ensureHasSource(components.NeedsSource(), repositories.NotUsed()); err != nil {
		return nil, err
	}
	// For source repos that are not yet coupled with a component, create components
	sourceComponents, err := c.componentsForRepos(repositories.NotUsed())
	if err != nil {
		return nil, err
	}
	// resolve the source repo components
	if err := c.resolve(sourceComponents); err != nil {
		return nil, err
	}
	components = append(components, sourceComponents...)

	glog.V(4).Infof("Code %v", repositories)
	glog.V(4).Infof("Components %v", components)

	if len(repositories) == 0 && len(components) == 0 {
		return nil, ErrNoInputs
	}

	pipelines, err := c.buildPipelines(components, app.Environment(environment))
	if err != nil {
		return nil, err
	}

	objects := app.Objects{}
	accept := app.NewAcceptFirst()
	for _, p := range pipelines {
		accepted, err := p.Objects(accept, acceptors)
		if err != nil {
			return nil, fmt.Errorf("can't setup %q: %v", p.From, err)
		}
		objects = append(objects, accepted...)
	}

	objects = app.AddServices(objects)

	templateObjects, err := c.buildTemplates(components, app.Environment(parameters))
	if err != nil {
		return nil, err
	}
	objects = append(objects, templateObjects...)

	buildNames := []string{}
	for _, obj := range objects {
		switch t := obj.(type) {
		case *buildapi.BuildConfig:
			buildNames = append(buildNames, t.Name)
		}
	}

	return &AppResult{
		List:       &kapi.List{Items: objects},
		BuildNames: buildNames,
		HasSource:  len(repositories) != 0,
		Namespace:  c.originNamespace,
	}, nil
}