func (d *Builder) construct(bprint b.Blueprint) (errs []error) {
	networkID, err := createNetworkIfNotExists(d.Docker, d.Config.PackageNamespace, bprint.Name)
	if err != nil {
		return []error{err}
	}

	runner := instruction.NewRunner(bprint.Name, d.Config.BestEffort, d.Config.DebugLoggingEnabled)
	results := make([]result, len(bprint.Homeservers))
	for i, hs := range bprint.Homeservers {
		res := d.constructHomeserver(bprint.Name, runner, hs, networkID)
		if res.err != nil {
			errs = append(errs, res.err)
			if res.containerID != "" {
				// something went wrong, but we have a container which may have interesting logs
				printLogs(d.Docker, res.containerID, res.contextStr)
			}
		}
		// kill the container
		defer func(r result) {
			killErr := d.Docker.ContainerKill(context.Background(), r.containerID, "KILL")
			if killErr != nil {
				d.log("%s : Failed to kill container %s: %s\n", r.contextStr, r.containerID, killErr)
			}
		}(res)
		results[i] = res
	}

	// commit containers
	for _, res := range results {
		if res.err != nil {
			continue
		}
		// collect and store access tokens as labels 'access_token_$userid: $token'
		labels := make(map[string]string)
		accessTokens := runner.AccessTokens(res.homeserver.Name)
		if len(bprint.KeepAccessTokensForUsers) > 0 {
			// only keep access tokens for specified users
			for _, userID := range bprint.KeepAccessTokensForUsers {
				tok, ok := accessTokens[userID]
				if ok {
					labels["access_token_"+userID] = tok
				}
			}
		} else {
			// keep all tokens
			for k, v := range accessTokens {
				labels["access_token_"+k] = v
			}
		}

		// Combine the labels for tokens and application services
		asLabels := labelsForApplicationServices(res.homeserver)
		for k, v := range asLabels {
			labels[k] = v
		}

		// commit the container
		commit, err := d.Docker.ContainerCommit(context.Background(), res.containerID, types.ContainerCommitOptions{
			Author:    "Complement",
			Pause:     true,
			Reference: "localhost/complement:" + res.contextStr,
			Config: &container.Config{
				Labels: labels,
			},
		})
		if err != nil {
			d.log("%s : failed to ContainerCommit: %s\n", res.contextStr, err)
			errs = append(errs, fmt.Errorf("%s : failed to ContainerCommit: %w", res.contextStr, err))
			continue
		}
		imageID := strings.Replace(commit.ID, "sha256:", "", 1)
		d.log("%s => %s\n", res.contextStr, imageID)
	}
	return errs
}
// construct all Homeservers sequentially then commits them
construct all Homeservers sequentially then commits them
// construct all Homeservers sequentially then commits them
func (d *Builder) construct(bprint b.Blueprint) (errs []error) {
	networkID, err := createNetworkIfNotExists(d.Docker, d.Config.PackageNamespace, bprint.Name)
	if err != nil {
		return []error{err}
	}
	runner := instruction.NewRunner(bprint.Name, d.Config.BestEffort, d.Config.DebugLoggingEnabled)
	results := make([]result, len(bprint.Homeservers))
	for i, hs := range bprint.Homeservers {
		res := d.constructHomeserver(bprint.Name, runner, hs, networkID)
		if res.err != nil {
			errs = append(errs, res.err)
			if res.containerID != "" {
				printLogs(d.Docker, res.containerID, res.contextStr)
			}
		}
		defer func(r result) {
			killErr := d.Docker.ContainerKill(context.Background(), r.containerID, "KILL")
			if killErr != nil {
				d.log("%s : Failed to kill container %s: %s\n", r.contextStr, r.containerID, killErr)
			}
		}(res)
		results[i] = res
	}
	for _, res := range results {
		if res.err != nil {
			continue
		}
		labels := make(map[string]string)
		accessTokens := runner.AccessTokens(res.homeserver.Name)
		if len(bprint.KeepAccessTokensForUsers) > 0 {
			for _, userID := range bprint.KeepAccessTokensForUsers {
				tok, ok := accessTokens[userID]
				if ok {
					labels["access_token_"+userID] = tok
				}
			}
		} else {
			for k, v := range accessTokens {
				labels["access_token_"+k] = v
			}
		}
		asLabels := labelsForApplicationServices(res.homeserver)
		for k, v := range asLabels {
			labels[k] = v
		}
		commit, err := d.Docker.ContainerCommit(context.Background(), res.containerID, types.ContainerCommitOptions{
			Author:    "Complement",
			Pause:     true,
			Reference: "localhost/complement:" + res.contextStr,
			Config: &container.Config{
				Labels: labels,
			},
		})
		if err != nil {
			d.log("%s : failed to ContainerCommit: %s\n", res.contextStr, err)
			errs = append(errs, fmt.Errorf("%s : failed to ContainerCommit: %w", res.contextStr, err))
			continue
		}
		imageID := strings.Replace(commit.ID, "sha256:", "", 1)
		d.log("%s => %s\n", res.contextStr, imageID)
	}
	return errs
}
func ( d * Builder ) construct ( bprint b . Blueprint ) ( errs [ ] error ) { networkID , err := createNetworkIfNotExists ( d . Docker , d . Config . PackageNamespace , bprint . Name ) if err != nil { return [ ] error { err } } runner := instruction . NewRunner ( bprint . Name , d . Config . BestEffort , d . Config . DebugLoggingEnabled ) results := make ( [ ] result , len ( bprint . Homeservers ) ) for i , hs := range bprint . Homeservers { res := d . constructHomeserver ( bprint . Name , runner , hs , networkID ) if res . err != nil { errs = append ( errs , res . err ) if res . containerID != " " { printLogs ( d . Docker , res . containerID , res . contextStr ) } } defer func ( r result ) { killErr := d . Docker . ContainerKill ( context . Background ( ) , r . containerID , " " ) if killErr != nil { d . log ( " \n " , r . contextStr , r . containerID , killErr ) } } ( res ) results [ i ] = res } for _ , res := range results { if res . err != nil { continue } labels := make ( map [ string ] string ) accessTokens := runner . AccessTokens ( res . homeserver . Name ) if len ( bprint . KeepAccessTokensForUsers ) > 0 { for _ , userID := range bprint . KeepAccessTokensForUsers { tok , ok := accessTokens [ userID ] if ok { labels [ " " + userID ] = tok } } } else { for k , v := range accessTokens { labels [ " " + k ] = v } } asLabels := labelsForApplicationServices ( res . homeserver ) for k , v := range asLabels { labels [ k ] = v } commit , err := d . Docker . ContainerCommit ( context . Background ( ) , res . containerID , types . ContainerCommitOptions { Author : " " , Pause : true , Reference : " " + res . contextStr , Config : & container . Config { Labels : labels , } , } ) if err != nil { d . log ( " \n " , res . contextStr , err ) errs = append ( errs , fmt . Errorf ( " " , res . contextStr , err ) ) continue } imageID := strings . Replace ( commit . ID , " " , " " , 1 ) d . log ( " \n " , res . contextStr , imageID ) } return errs }
construct all Homeservers sequentially then commits them
construct all Homeservers sequentially then commits them
// something went wrong, but we have a container which may have interesting logs // kill the container // commit containers // collect and store access tokens as labels 'access_token_$userid: $token' // only keep access tokens for specified users // keep all tokens // Combine the labels for tokens and application services // commit the container