func (sc *ServiceConfig) Status() ([]ServiceStatus, error) { command, err := sc.GetCommand() if err != nil { return nil, errors.WithStack(err) } status := ServiceStatus{ Service: sc, Status: "STOPPED", } if command.Pid != 0 { status.Status = "RUNNING" status.Pid = command.Pid proc, err := process.NewProcess(int32(command.Pid)) if err != nil { return nil, errors.WithStack(err) } epochStart, err := proc.CreateTime() if err != nil { return nil, errors.WithStack(err) } status.StartTime = time.Unix(epochStart/1000, 0) status.Ports, err = sc.getPorts(proc) if err != nil { return nil, errors.WithStack(err) } } return []ServiceStatus{ status, }, nil }
func (sc *ServiceCommand) waitForAnyPort(cancel <-chan struct{}, command *exec.Cmd) error { for true { time.Sleep(100 * time.Millisecond) select { case <-cancel: return nil default: } connections, err := net.Connections("all") if err != nil { return errors.WithStack(err) } proc, err := process.NewProcess(int32(command.Process.Pid)) if err != nil { return errors.WithStack(err) } if hasPort(proc, connections) { return nil } } return errors.New("exited check loop unexpectedly") }
func joinSwarm(existingClient *docker.Client, newClient *docker.Client, addr string) error { swarmInfo, err := existingClient.InspectSwarm(nil) if err != nil { return errors.WithStack(err) } dockerInfo, err := existingClient.Info() if err != nil { return errors.WithStack(err) } if len(dockerInfo.Swarm.RemoteManagers) == 0 { return errors.Errorf("no remote managers found in node %#v", dockerInfo) } addrs := make([]string, len(dockerInfo.Swarm.RemoteManagers)) for i, peer := range dockerInfo.Swarm.RemoteManagers { addrs[i] = peer.Addr } host := tsuruNet.URLToHost(addr) opts := docker.JoinSwarmOptions{ JoinRequest: swarm.JoinRequest{ ListenAddr: fmt.Sprintf("0.0.0.0:%d", swarmConfig.swarmPort), AdvertiseAddr: host, JoinToken: swarmInfo.JoinTokens.Worker, RemoteAddrs: addrs, }, } err = newClient.JoinSwarm(opts) if err != nil && err != docker.ErrNodeAlreadyInSwarm { return errors.WithStack(err) } return redistributeManagers(existingClient) }
// SearchFullText Search returns work items for the given query func (r *GormSearchRepository) SearchFullText(ctx context.Context, rawSearchString string, start *int, limit *int) ([]*app.WorkItem, uint64, error) { // parse // generateSearchQuery // .... parsedSearchDict, err := parseSearchString(rawSearchString) if err != nil { return nil, 0, errs.WithStack(err) } sqlSearchQueryParameter := generateSQLSearchInfo(parsedSearchDict) var rows []workitem.WorkItem rows, count, err := r.search(ctx, sqlSearchQueryParameter, parsedSearchDict.workItemTypes, start, limit) if err != nil { return nil, 0, errs.WithStack(err) } result := make([]*app.WorkItem, len(rows)) for index, value := range rows { var err error // FIXME: Against best practice http://go-database-sql.org/retrieving.html wiType, err := r.wir.LoadTypeFromDB(ctx, value.Type) if err != nil { return nil, 0, errors.NewInternalError(err.Error()) } result[index], err = convertFromModel(*wiType, value) if err != nil { return nil, 0, errors.NewConversionError(err.Error()) } } return result, count, nil }
func updateDBSwarmNodes(client *docker.Client) error { nodes, err := listValidNodes(client) if err != nil { return errors.WithStack(err) } var addrs []string for _, n := range nodes { if n.ManagerStatus == nil { continue } addr := n.Spec.Annotations.Labels[labelNodeDockerAddr.String()] if addr == "" { continue } addrs = append(addrs, addr) } coll, err := nodeAddrCollection() if err != nil { return err } defer coll.Close() _, err = coll.UpsertId(uniqueDocumentID, bson.M{"$set": bson.M{"addresses": addrs}}) if err != nil { return errors.WithStack(err) } return nil }
func (p *swarmProvisioner) Destroy(a provision.App) error { client, err := chooseDBSwarmNode() if err != nil { return err } multiErrors := tsuruErrors.NewMultiError() processes, err := allAppProcesses(a.GetName()) if err != nil { multiErrors.Add(err) } for _, p := range processes { name := serviceNameForApp(a, p) err = client.RemoveService(docker.RemoveServiceOptions{ ID: name, }) if err != nil { if _, notFound := err.(*docker.NoSuchService); !notFound { multiErrors.Add(errors.WithStack(err)) } } } err = client.RemoveNetwork(networkNameForApp(a)) if err != nil { multiErrors.Add(errors.WithStack(err)) } if multiErrors.Len() > 0 { return multiErrors } return nil }
func (mgm tokenManager) Extract(tokenString string) (*account.Identity, error) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return mgm.publicKey, nil }) if err != nil { return nil, errors.WithStack(err) } if !token.Valid { return nil, errors.New("Token not valid") } claimedUUID := token.Claims.(jwt.MapClaims)["sub"] if claimedUUID == nil { return nil, errors.New("Subject can not be nil") } // in case of nil UUID, below type casting will fail hence we need above check id, err := uuid.FromString(token.Claims.(jwt.MapClaims)["sub"].(string)) if err != nil { return nil, errors.WithStack(err) } ident := account.Identity{ ID: id, Username: token.Claims.(jwt.MapClaims)["preferred_username"].(string), } return &ident, nil }
func encodeToken(referal *url.URL, outhToken *oauth2.Token) error { str := outhToken.Extra("expires_in") expiresIn, err := strconv.Atoi(fmt.Sprintf("%v", str)) if err != nil { return errs.WithStack(errors.New("cant convert expires_in to integer " + err.Error())) } str = outhToken.Extra("refresh_expires_in") refreshExpiresIn, err := strconv.Atoi(fmt.Sprintf("%v", str)) if err != nil { return errs.WithStack(errors.New("cant convert refresh_expires_in to integer " + err.Error())) } tokenData := &app.TokenData{ AccessToken: &outhToken.AccessToken, RefreshToken: &outhToken.RefreshToken, TokenType: &outhToken.TokenType, ExpiresIn: &expiresIn, RefreshExpiresIn: &refreshExpiresIn, } b, err := json.Marshal(tokenData) if err != nil { return errs.WithStack(errors.New("cant marshal token data struct " + err.Error())) } parameters := url.Values{} parameters.Add("token", outhToken.AccessToken) // Temporary keep the old "token" param. We will drop this param as soon as UI adopt the new json param. parameters.Add("token_json", string(b)) referal.RawQuery = parameters.Encode() return nil }
func run(c *cli.Context) error { args := c.Args() if len(args) < 3 { return errors.New("a directory, log file and command is required") } workingDir := os.ExpandEnv(args[0]) logFile := os.ExpandEnv(args[1]) fullCommand := os.ExpandEnv(args[2]) command, cmdArgs, err := parseCommand(fullCommand) if err != nil { return errors.WithStack(err) } log, err := os.Create(logFile) if err != nil { return errors.WithStack(err) } cmd := exec.Command(command, cmdArgs...) fmt.Println(cmd.Path) cmd.Dir = workingDir cmd.Stdout = log cmd.Stderr = log return cmd.Run() }
// Transactional executes the given function in a transaction. If todo returns an error, the transaction is rolled back func Transactional(db DB, todo func(f Application) error) error { var tx Transaction var err error if tx, err = db.BeginTransaction(); err != nil { log.Error(nil, map[string]interface{}{ "err": err, }, "database BeginTransaction failed!") return errors.WithStack(err) } if err := todo(tx); err != nil { log.Debug(nil, map[string]interface{}{ "pkg": "application", }, "Rolling back the transaction...") tx.Rollback() log.Error(nil, map[string]interface{}{ "err": err, }, "database transaction failed!") return errors.WithStack(err) } log.Debug(nil, map[string]interface{}{ "pkg": "application", }, "Commit the transaction!") return tx.Commit() }
func (p *swarmProvisioner) ArchiveDeploy(a provision.App, archiveURL string, evt *event.Event) (imgID string, err error) { baseImage := image.GetBuildImage(a) buildingImage, err := image.AppNewImageName(a.GetName()) if err != nil { return "", errors.WithStack(err) } client, err := chooseDBSwarmNode() if err != nil { return "", err } cmds := dockercommon.ArchiveDeployCmds(a, archiveURL) srvID, task, err := runOnceBuildCmds(client, a, cmds, baseImage, buildingImage, evt) if srvID != "" { defer removeServiceAndLog(client, srvID) } if err != nil { return "", err } _, err = commitPushBuildImage(client, buildingImage, task.Status.ContainerStatus.ContainerID, a) if err != nil { return "", err } err = deployProcesses(client, a, buildingImage, nil) if err != nil { return "", errors.WithStack(err) } return buildingImage, nil }
// ValidateCorrectSourceAndTargetType returns an error if the Path of // the source WIT as defined by the work item link type is not part of // the actual source's WIT; the same applies for the target. func (r *GormWorkItemLinkRepository) ValidateCorrectSourceAndTargetType(ctx context.Context, sourceID, targetID uint64, linkTypeID satoriuuid.UUID) error { linkType, err := r.workItemLinkTypeRepo.LoadTypeFromDBByID(ctx, linkTypeID) if err != nil { return errs.WithStack(err) } // Fetch the source work item source, err := r.workItemRepo.LoadFromDB(ctx, strconv.FormatUint(sourceID, 10)) if err != nil { return errs.WithStack(err) } // Fetch the target work item target, err := r.workItemRepo.LoadFromDB(ctx, strconv.FormatUint(targetID, 10)) if err != nil { return errs.WithStack(err) } // Fetch the concrete work item types of the target and the source. sourceWorkItemType, err := r.workItemTypeRepo.LoadTypeFromDB(ctx, source.Type) if err != nil { return errs.WithStack(err) } targetWorkItemType, err := r.workItemTypeRepo.LoadTypeFromDB(ctx, target.Type) if err != nil { return errs.WithStack(err) } // Check type paths if !sourceWorkItemType.IsTypeOrSubtypeOf(linkType.SourceTypeName) { return errors.NewBadParameterError("source work item type", source.Type) } if !targetWorkItemType.IsTypeOrSubtypeOf(linkType.TargetTypeName) { return errors.NewBadParameterError("target work item type", target.Type) } return nil }
func LoadConfigWithDir(reader io.Reader, workingDir string, edwardVersion string, logger common.Logger) (Config, error) { config, err := loadConfigContents(reader, workingDir, logger) if err != nil { return Config{}, errors.WithStack(err) } if config.MinEdwardVersion != "" && edwardVersion != "" { // Check that this config is supported by this version minVersion, err1 := version.NewVersion(config.MinEdwardVersion) if err1 != nil { return Config{}, errors.WithStack(err) } currentVersion, err2 := version.NewVersion(edwardVersion) if err2 != nil { return Config{}, errors.WithStack(err) } if currentVersion.LessThan(minVersion) { return Config{}, errors.New("this config requires at least version " + config.MinEdwardVersion) } } err = config.initMaps() config.printf("Config loaded with: %d groups and %d services\n", len(config.GroupMap), len(config.ServiceMap)) return config, errors.WithStack(err) }
func (c *Config) loadImports() error { c.printf("Loading imports\n") for _, i := range c.Imports { var cPath string if filepath.IsAbs(i) { cPath = i } else { cPath = filepath.Join(c.workingDir, i) } c.printf("Loading: %v\n", cPath) r, err := os.Open(cPath) if err != nil { return errors.WithStack(err) } cfg, err := loadConfigContents(r, filepath.Dir(cPath), c.Logger) if err != nil { return errors.WithStack(err) } err = c.importConfig(cfg) if err != nil { return errors.WithStack(err) } } return nil }
func (p *swarmProvisioner) Shell(opts provision.ShellOptions) error { client, err := chooseDBSwarmNode() if err != nil { return err } tasks, err := runningTasksForApp(client, opts.App, opts.Unit) if err != nil { return err } if len(tasks) == 0 { if opts.Unit != "" { return &provision.UnitNotFoundError{ID: opts.Unit} } return provision.ErrEmptyApp } nodeClient, err := clientForNode(client, tasks[0].NodeID) if err != nil { return err } cmds := []string{"/usr/bin/env", "TERM=" + opts.Term, "bash", "-l"} execCreateOpts := docker.CreateExecOptions{ AttachStdin: true, AttachStdout: true, AttachStderr: true, Cmd: cmds, Container: tasks[0].Status.ContainerStatus.ContainerID, Tty: true, } exec, err := nodeClient.CreateExec(execCreateOpts) if err != nil { return errors.WithStack(err) } startExecOptions := docker.StartExecOptions{ InputStream: opts.Conn, OutputStream: opts.Conn, ErrorStream: opts.Conn, Tty: true, RawTerminal: true, } errs := make(chan error, 1) go func() { errs <- nodeClient.StartExec(exec.ID, startExecOptions) }() execInfo, err := nodeClient.InspectExec(exec.ID) for !execInfo.Running && err == nil { select { case startErr := <-errs: return startErr default: execInfo, err = nodeClient.InspectExec(exec.ID) } } if err != nil { return errors.WithStack(err) } nodeClient.ResizeExecTTY(exec.ID, opts.Height, opts.Width) return <-errs }
func (c Config) Save(writer io.Writer) error { c.printf("Saving config") content, err := json.MarshalIndent(c, "", " ") if err != nil { return errors.WithStack(err) } _, err = writer.Write(content) return errors.WithStack(err) }
// executeSQLFile loads the given filename from the packaged SQL files and // executes it on the given database func executeSQLFile(filename string) fn { return func(db *sql.Tx) error { data, err := Asset(filename) if err != nil { return errs.WithStack(err) } _, err = db.Exec(string(data)) return errs.WithStack(err) } }
func TestConvertExistingWorkItem(t *testing.T) { resource.Require(t, resource.Database) // Setting up the dependent tracker query and tracker data in the Database tr := Tracker{URL: "https://api.github.com/", Type: ProviderGithub} db = db.Create(&tr) require.Nil(t, db.Error) tq := TrackerQuery{Query: "some random query", Schedule: "0 0 0 * * *", TrackerID: tr.ID} db = db.Create(&tq) require.Nil(t, db.Error) defer cleaner.DeleteCreatedEntities(db)() t.Log("Created Tracker Query and Tracker") models.Transactional(db, func(tx *gorm.DB) error { t.Log("Adding a work item which wasn't present.") remoteItemData := TrackerItemContent{ Content: []byte(`{"title":"linking","url":"http://github.com/sbose/api/testonly/1","state":"closed","body":"body of issue","user.login":"******","assignee.login":"******"}`), ID: "http://github.com/sbose/api/testonly/1", } workItem, err := convert(tx, int(tq.ID), remoteItemData, ProviderGithub) assert.Nil(t, err) assert.Equal(t, "linking", workItem.Fields[workitem.SystemTitle]) assert.Equal(t, "sbose78", workItem.Fields[workitem.SystemCreator]) assert.Equal(t, "pranav", workItem.Fields[workitem.SystemAssignees].([]interface{})[0]) assert.Equal(t, "closed", workItem.Fields[workitem.SystemState]) return errors.WithStack(err) }) t.Log("Updating the existing work item when it's reimported.") models.Transactional(db, func(tx *gorm.DB) error { remoteItemDataUpdated := TrackerItemContent{ Content: []byte(`{"title":"linking-updated","url":"http://github.com/api/testonly/1","state":"closed","body":"body of issue","user.login":"******","assignee.login":"******"}`), ID: "http://github.com/sbose/api/testonly/1", } workItemUpdated, err := convert(tx, int(tq.ID), remoteItemDataUpdated, ProviderGithub) assert.Nil(t, err) assert.Equal(t, "linking-updated", workItemUpdated.Fields[workitem.SystemTitle]) assert.Equal(t, "sbose78", workItemUpdated.Fields[workitem.SystemCreator]) assert.Equal(t, "pranav", workItemUpdated.Fields[workitem.SystemAssignees].([]interface{})[0]) assert.Equal(t, "closed", workItemUpdated.Fields[workitem.SystemState]) wir := workitem.NewWorkItemRepository(tx) wir.Delete(context.Background(), workItemUpdated.ID) return errors.WithStack(err) }) }
func (sc *ServiceConfig) Launch(cfg OperationConfig) error { if cfg.IsExcluded(sc) { return nil } command, err := sc.GetCommand() if err != nil { return errors.WithStack(err) } return errors.WithStack(command.StartAsync(cfg)) }
func (sc *ServiceConfig) Build(cfg OperationConfig) error { if cfg.IsExcluded(sc) { return nil } command, err := sc.GetCommand() if err != nil { return errors.WithStack(err) } return errors.WithStack(command.BuildSync(false)) }
func (p *swarmProvisioner) AddNode(opts provision.AddNodeOptions) error { init := false existingClient, err := chooseDBSwarmNode() if err != nil && errors.Cause(err) != errNoSwarmNode { return err } err = addNodeCredentials(opts) if err != nil { return err } newClient, err := newClient(opts.Address) if err != nil { return err } if existingClient == nil { err = initSwarm(newClient, opts.Address) existingClient = newClient init = true } else { err = joinSwarm(existingClient, newClient, opts.Address) } if err != nil { return err } dockerInfo, err := newClient.Info() if err != nil { return errors.WithStack(err) } nodeData, err := existingClient.InspectNode(dockerInfo.Swarm.NodeID) if err != nil { return errors.WithStack(err) } nodeData.Spec.Annotations.Labels = map[string]string{ labelNodeDockerAddr.String(): opts.Address, } for k, v := range opts.Metadata { nodeData.Spec.Annotations.Labels[k] = v } err = existingClient.UpdateNode(dockerInfo.Swarm.NodeID, docker.UpdateNodeOptions{ Version: nodeData.Version.Index, NodeSpec: nodeData.Spec, }) if err != nil { return errors.WithStack(err) } err = updateDBSwarmNodes(existingClient) if err != nil { return err } if init { return p.ensureNodeContainersCreated() } return nil }
// Load returns a single Identity as a Database Model // This is more for use internally, and probably not what you want in your controllers func (m *GormIdentityRepository) Load(ctx context.Context, id uuid.UUID) (*Identity, error) { defer goa.MeasureSince([]string{"goa", "db", "identity", "load"}, time.Now()) var native Identity err := m.db.Table(m.TableName()).Where("id = ?", id).Find(&native).Error if err == gorm.ErrRecordNotFound { return nil, errors.WithStack(err) } return &native, errors.WithStack(err) }
func (sc *ServiceConfig) Start(cfg OperationConfig) error { if cfg.IsExcluded(sc) { return nil } err := sc.Build(cfg) if err != nil { return errors.WithStack(err) } err = sc.Launch(cfg) return errors.WithStack(err) }
func loadIgnores(path string, currentIgnores *ignore.GitIgnore) (*ignore.GitIgnore, error) { ignoreFile := filepath.Join(path, ".edwardignore") if _, err := os.Stat(ignoreFile); err != nil { if os.IsNotExist(err) { return currentIgnores, nil } return currentIgnores, errors.WithStack(err) } ignores, err := ignore.CompileIgnoreFile(ignoreFile) return ignores, errors.WithStack(err) }
// enrichLinkSingle includes related resources in the link's "included" array func enrichLinkSingle(ctx *workItemLinkContext, link *app.WorkItemLinkSingle) error { // include link type linkType, err := ctx.Application.WorkItemLinkTypes().Load(ctx.Context, link.Data.Relationships.LinkType.Data.ID) if err != nil { return errs.WithStack(err) } link.Included = append(link.Included, linkType.Data) // include link category linkCat, err := ctx.Application.WorkItemLinkCategories().Load(ctx.Context, linkType.Data.Relationships.LinkCategory.Data.ID) if err != nil { return errs.WithStack(err) } link.Included = append(link.Included, linkCat.Data) // TODO(kwk): include source work item type (once #559 is merged) // sourceWit, err := appl.WorkItemTypes().Load(ctx, linkType.Data.Relationships.SourceType.Data.ID) // if err != nil { // return errs.WithStack(err) // } // link.Included = append(link.Included, sourceWit.Data) // TODO(kwk): include target work item type (once #559 is merged) // targetWit, err := appl.WorkItemTypes().Load(ctx, linkType.Data.Relationships.TargetType.Data.ID) // if err != nil { // return errs.WithStack(err) // } // link.Included = append(link.Included, targetWit.Data) // TODO(kwk): include source work item sourceWi, err := ctx.Application.WorkItems().Load(ctx.Context, link.Data.Relationships.Source.Data.ID) if err != nil { return errs.WithStack(err) } link.Included = append(link.Included, ConvertWorkItem(ctx.RequestData, sourceWi)) // TODO(kwk): include target work item targetWi, err := ctx.Application.WorkItems().Load(ctx.Context, link.Data.Relationships.Target.Data.ID) if err != nil { return errs.WithStack(err) } link.Included = append(link.Included, ConvertWorkItem(ctx.RequestData, targetWi)) // Add links to individual link data element selfURL := rest.AbsoluteURL(ctx.RequestData, ctx.LinkFunc(*link.Data.ID)) link.Data.Links = &app.GenericLinks{ Self: &selfURL, } return nil }
func (sc *ServiceCommand) waitUntilLive(command *exec.Cmd) error { sc.printf("Waiting for %v to start.\n", sc.Service.Name) var startCheck func(cancel <-chan struct{}) error if sc.Service.LaunchChecks != nil && len(sc.Service.LaunchChecks.LogText) > 0 { startCheck = func(cancel <-chan struct{}) error { return errors.WithStack( sc.waitForLogText(sc.Service.LaunchChecks.LogText, cancel), ) } } else if sc.Service.LaunchChecks != nil && len(sc.Service.LaunchChecks.Ports) > 0 { startCheck = func(cancel <-chan struct{}) error { return errors.WithStack( sc.waitForListeningPorts(sc.Service.LaunchChecks.Ports, cancel, command), ) } } else { startCheck = func(cancel <-chan struct{}) error { return errors.WithStack( sc.waitForAnyPort(cancel, command), ) } } processFinished := func(cancel <-chan struct{}) error { // Wait until the process exists command.Wait() select { case <-cancel: return nil default: } return errors.New("service terminated prematurely") } timeout := time.NewTimer(30 * time.Second) defer timeout.Stop() done := make(chan struct{}) defer close(done) select { case result := <-cancelableWait(done, startCheck): return errors.WithStack(result.error) case result := <-cancelableWait(done, processFinished): return errors.WithStack(result.error) case <-timeout.C: return errors.New("Waiting for service timed out") } }
func provideRemoteData(dataURL string) ([]byte, error) { response, err := http.Get(dataURL) if err != nil { return nil, errors.WithStack(err) } defer response.Body.Close() responseData, err := ioutil.ReadAll(response.Body) if err != nil { return nil, errors.WithStack(err) } return responseData, nil }
func startWatch(watches *services.ServiceWatch, cfg services.OperationConfig) (*fsnotify.Watcher, error) { fmt.Printf("Watching %v paths for service %v\n", len(watches.IncludedPaths), watches.Service.GetName()) watcher, err := fsnotify.NewWatcher() if err != nil { return nil, errors.WithStack(err) } go func() { for { select { case event := <-watcher.Events: if event.Op&fsnotify.Write == fsnotify.Write { fmt.Printf("File edited: %v\n", event.Name) var wasExcluded bool for _, excluded := range watches.ExcludedPaths { if strings.HasPrefix(event.Name, excluded) { fmt.Println("File is under excluded path:", excluded) wasExcluded = true break } } if wasExcluded { continue } fmt.Printf("Rebuilding %v\n", watches.Service.GetName()) err = rebuildService(watches.Service, cfg) if err != nil { fmt.Printf("Could not rebuild %v: %v\n", watches.Service.GetName(), err) } } case err := <-watcher.Errors: if err != nil { log.Println("error:", err) } } } }() for _, dir := range watches.IncludedPaths { err = watcher.Add(dir) if err != nil { watcher.Close() return nil, errors.WithStack(err) } } return watcher, nil }
// enrichLinkList includes related resources in the linkArr's "included" element func enrichLinkList(ctx *workItemLinkContext, linkArr *app.WorkItemLinkList) error { // include link types typeDataArr, err := getTypesOfLinks(ctx, linkArr.Data) if err != nil { return errs.WithStack(err) } // Convert slice of objects to slice of interface (see https://golang.org/doc/faq#convert_slice_of_interface) interfaceArr := make([]interface{}, len(typeDataArr)) for i, v := range typeDataArr { interfaceArr[i] = v } linkArr.Included = append(linkArr.Included, interfaceArr...) // include link categories catDataArr, err := getCategoriesOfLinkTypes(ctx, typeDataArr) if err != nil { return errs.WithStack(err) } // Convert slice of objects to slice of interface (see https://golang.org/doc/faq#convert_slice_of_interface) interfaceArr = make([]interface{}, len(catDataArr)) for i, v := range catDataArr { interfaceArr[i] = v } linkArr.Included = append(linkArr.Included, interfaceArr...) // TODO(kwk): Include WIs from source and target workItemDataArr, err := getWorkItemsOfLinks(ctx, linkArr.Data) if err != nil { return errs.WithStack(err) } // Convert slice of objects to slice of interface (see https://golang.org/doc/faq#convert_slice_of_interface) interfaceArr = make([]interface{}, len(workItemDataArr)) for i, v := range workItemDataArr { interfaceArr[i] = v } linkArr.Included = append(linkArr.Included, interfaceArr...) // TODO(kwk): Include WITs (once #559 is merged) // Add links to individual link data element for _, link := range linkArr.Data { selfURL := rest.AbsoluteURL(ctx.RequestData, ctx.LinkFunc(*link.ID)) link.Links = &app.GenericLinks{ Self: &selfURL, } } return nil }
// PopulateCommonTypes makes sure the database is populated with the correct types (e.g. bug etc.) func PopulateCommonTypes(ctx context.Context, db *gorm.DB, witr *workitem.GormWorkItemTypeRepository) error { if err := createOrUpdateSystemPlannerItemType(ctx, witr, db); err != nil { return errs.WithStack(err) } workitem.ClearGlobalWorkItemTypeCache() // Clear the WIT cache after updating existing WITs if err := createOrUpdatePlannerItemExtension(workitem.SystemUserStory, ctx, witr, db); err != nil { return errs.WithStack(err) } if err := createOrUpdatePlannerItemExtension(workitem.SystemValueProposition, ctx, witr, db); err != nil { return errs.WithStack(err) } if err := createOrUpdatePlannerItemExtension(workitem.SystemFundamental, ctx, witr, db); err != nil { return errs.WithStack(err) } if err := createOrUpdatePlannerItemExtension(workitem.SystemExperience, ctx, witr, db); err != nil { return errs.WithStack(err) } if err := createOrUpdatePlannerItemExtension(workitem.SystemScenario, ctx, witr, db); err != nil { return errs.WithStack(err) } if err := createOrUpdatePlannerItemExtension(workitem.SystemFeature, ctx, witr, db); err != nil { return errs.WithStack(err) } if err := createOrUpdatePlannerItemExtension(workitem.SystemBug, ctx, witr, db); err != nil { return errs.WithStack(err) } workitem.ClearGlobalWorkItemTypeCache() // Clear the WIT cache after updating existing WITs return nil }