Exemple #1
0
func (c *Core) appContext(f *appfile.File) (*app.Context, error) {
	// Whether or not this is the root Appfile
	root := f.ID == c.appfile.ID

	// We need the configuration for the active infrastructure
	// so that we can build the tuple below
	config := f.ActiveInfrastructure()
	if config == nil {
		return nil, fmt.Errorf(
			"infrastructure not found in appfile: %s",
			f.Project.Infrastructure)
	}

	// The tuple we're looking for is the application type, the
	// infrastructure type, and the infrastructure flavor. Build that
	// tuple.
	tuple := app.Tuple{
		App:         f.Application.Type,
		Infra:       config.Type,
		InfraFlavor: config.Flavor,
	}

	// The output directory for data. This is either the main app so
	// it goes directly into "app" or it is a dependency and goes into
	// a dep folder.
	outputDir := filepath.Join(c.compileDir, "app")
	if !root {
		outputDir = filepath.Join(
			c.compileDir, fmt.Sprintf("dep-%s", f.ID))
	}

	// The cache directory for this app
	cacheDir := filepath.Join(c.dataDir, "cache", f.ID)
	if err := os.MkdirAll(cacheDir, 0755); err != nil {
		return nil, fmt.Errorf(
			"error making cache directory '%s': %s",
			cacheDir, err)
	}

	// The directory for global data
	globalDir := filepath.Join(c.dataDir, "global-data")
	if err := os.MkdirAll(globalDir, 0755); err != nil {
		return nil, fmt.Errorf(
			"error making global data directory '%s': %s",
			globalDir, err)
	}

	// Build the contexts for the foundations. We use this
	// to also compile the list of foundation dirs.
	foundationDirs := make([]string, len(config.Foundations))
	for i, f := range config.Foundations {
		foundationDirs[i] = filepath.Join(
			outputDir, fmt.Sprintf("foundation-%s", f.Name))
	}

	// Get the dev IP address
	ipDB := &localaddr.CachedDB{
		DB:        &localaddr.DB{Path: filepath.Join(c.dataDir, "ip.db")},
		CachePath: filepath.Join(c.localDir, "dev_ip"),
	}
	ip, err := ipDB.IP()
	if err != nil {
		return nil, fmt.Errorf(
			"Error retrieving dev IP address: %s", err)
	}

	// Get the metadata
	var compileResult *app.CompileResult
	md, err := c.compileMetadata()
	if err != nil {
		return nil, fmt.Errorf(
			"Error loading compilation metadata: %s", err)
	}
	if md != nil {
		if root {
			compileResult = md.App
		} else {
			compileResult = md.AppDeps[f.ID]
		}
	}

	// Get the customizations. If we don't have any at all, we fast-path
	// this by doing nothing. If we do, we have to make a deep copy in
	// order to prune out the irrelevant ones.
	if f.Customization != nil && len(f.Customization.Raw) > 0 {
		// Perform a deep copy of the Appfile so we can modify it
		fRaw, err := copystructure.Copy(f)
		if err != nil {
			return nil, err
		}
		f = fRaw.(*appfile.File)

		// Get the app-only customizations and set it on the Appfile
		cs := f.Customization.Filter("app")
		f.Customization = &appfile.CustomizationSet{Raw: cs}
	}

	return &app.Context{
		CompileResult: compileResult,
		Dir:           outputDir,
		CacheDir:      cacheDir,
		LocalDir:      c.localDir,
		GlobalDir:     globalDir,
		Tuple:         tuple,
		Application:   f.Application,
		DevIPAddress:  ip.String(),
		Shared: context.Shared{
			Appfile:        f,
			FoundationDirs: foundationDirs,
			InstallDir:     filepath.Join(c.dataDir, "binaries"),
			Directory:      c.dir,
			Ui:             c.ui,
		},
	}, nil
}