func (c *Cluster) bootstrapLayer1(instances []*Instance) error { inst := instances[0] c.ClusterDomain = fmt.Sprintf("flynn-%s.local", random.String(16)) c.ControllerKey = random.String(16) c.BackoffPeriod = 5 * time.Second rd, wr := io.Pipe() ips := make([]string, len(instances)) for i, inst := range instances { ips[i] = inst.IP } var cmdErr error go func() { command := fmt.Sprintf( "CLUSTER_DOMAIN=%s CONTROLLER_KEY=%s BACKOFF_PERIOD=%fs flynn-host bootstrap --json --min-hosts=%d --peer-ips=%s /etc/flynn-bootstrap.json", c.ClusterDomain, c.ControllerKey, c.BackoffPeriod.Seconds(), len(instances), strings.Join(ips, ","), ) cmdErr = inst.Run(command, &Streams{Stdout: wr, Stderr: os.Stderr}) wr.Close() }() // grab the controller tls pin from the bootstrap output var cert controllerCert dec := json.NewDecoder(rd) for { var msg bootstrapMsg if err := dec.Decode(&msg); err == io.EOF { break } else if err != nil { return fmt.Errorf("failed to parse bootstrap JSON output: %s", err) } c.log("bootstrap ===>", msg.Id, msg.State) if msg.State == "error" { c.log(msg.Error) } if msg.Id == "controller-cert" && msg.State == "done" { json.Unmarshal(msg.Data, &cert) } } if cmdErr != nil { return cmdErr } if cert.Pin == "" { return errors.New("could not determine controller cert from bootstrap output") } c.ControllerPin = cert.Pin // grab the router IP from discoverd disc := discoverd.NewClientWithURL(fmt.Sprintf("http://%s:1111", inst.IP)) leader, err := disc.Service("router-api").Leader() if err != nil { return fmt.Errorf("could not detect router ip: %s", err) } if err = setLocalDNS([]string{c.ClusterDomain, c.ControllerDomain()}, leader.Host()); err != nil { return fmt.Errorf("could not set cluster DNS entries: %s", err) } c.RouterIP = leader.Host() return nil }
func (s *CLISuite) TestExportImport(t *c.C) { srcApp := "app-export" + random.String(8) dstApp := "app-import" + random.String(8) // create and push app+db r := s.newGitRepo(t, "http") t.Assert(r.flynn("create", srcApp), Succeeds) t.Assert(r.flynn("key", "add", r.ssh.Pub), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) t.Assert(r.flynn("resource", "add", "postgres"), Succeeds) t.Assert(r.flynn("pg", "psql", "--", "-c", "CREATE table foos (data text); INSERT INTO foos (data) VALUES ('foobar')"), Succeeds) // export app file := filepath.Join(t.MkDir(), "export.tar") t.Assert(r.flynn("export", "-f", file), Succeeds) // remove db table from source app t.Assert(r.flynn("pg", "psql", "--", "-c", "DROP TABLE foos"), Succeeds) // import app t.Assert(r.flynn("import", "--name", dstApp, "--file", file), Succeeds) // test db was imported query := r.flynn("-a", dstApp, "pg", "psql", "--", "-c", "SELECT * FROM foos") t.Assert(query, SuccessfulOutputContains, "foobar") // wait for it to start _, err := s.discoverdClient(t).Instances(dstApp+"-web", 10*time.Second) t.Assert(err, c.IsNil) }
func (s *CLISuite) TestExportImport(t *c.C) { srcApp := "app-export" + random.String(8) dstApp := "app-import" + random.String(8) // create app r := s.newGitRepo(t, "http") t.Assert(r.flynn("create", srcApp), Succeeds) // exporting the app without a release should work file := filepath.Join(t.MkDir(), "export.tar") t.Assert(r.flynn("export", "-f", file), Succeeds) assertExportContains := func(paths ...string) { cmd := r.sh(fmt.Sprintf("tar --list --file=%s --strip=1 --show-transformed", file)) t.Assert(cmd, Outputs, strings.Join(paths, "\n")+"\n") } assertExportContains("app.json", "routes.json") // exporting the app with an artifact-less release should work t.Assert(r.flynn("env", "set", "FOO=BAR"), Succeeds) t.Assert(r.flynn("export", "-f", file), Succeeds) assertExportContains("app.json", "routes.json", "release.json") // release the app and provision some dbs t.Assert(r.git("push", "flynn", "master"), Succeeds) t.Assert(r.flynn("resource", "add", "postgres"), Succeeds) t.Assert(r.flynn("pg", "psql", "--", "-c", "CREATE table foos (data text); INSERT INTO foos (data) VALUES ('foobar')"), Succeeds) t.Assert(r.flynn("resource", "add", "mysql"), Succeeds) t.Assert(r.flynn("mysql", "console", "--", "-e", "CREATE TABLE foos (data TEXT); INSERT INTO foos (data) VALUES ('foobar')"), Succeeds) // export app t.Assert(r.flynn("export", "-f", file), Succeeds) assertExportContains( "app.json", "routes.json", "release.json", "artifact.json", "formation.json", "slug.tar.gz", "postgres.dump", "mysql.dump", ) // remove db tables from source app t.Assert(r.flynn("pg", "psql", "--", "-c", "DROP TABLE foos"), Succeeds) t.Assert(r.flynn("mysql", "console", "--", "-e", "DROP TABLE foos"), Succeeds) // remove the git remote t.Assert(r.git("remote", "remove", "flynn"), Succeeds) // import app t.Assert(r.flynn("import", "--name", dstApp, "--file", file), Succeeds) // test dbs were imported query := r.flynn("-a", dstApp, "pg", "psql", "--", "-c", "SELECT * FROM foos") t.Assert(query, SuccessfulOutputContains, "foobar") query = r.flynn("-a", dstApp, "mysql", "console", "--", "-e", "SELECT * FROM foos") t.Assert(query, SuccessfulOutputContains, "foobar") // wait for it to start _, err := s.discoverdClient(t).Instances(dstApp+"-web", 10*time.Second) t.Assert(err, c.IsNil) }
func (c *Cluster) bootstrapFlynn() error { inst := c.instances[0] c.ControllerDomain = fmt.Sprintf("flynn-%s.local", random.String(16)) c.ControllerKey = random.String(16) rd, wr := io.Pipe() var cmdErr error go func() { command := fmt.Sprintf( "docker run -e=DISCOVERD=%s:1111 -e CONTROLLER_DOMAIN=%s -e CONTROLLER_KEY=%s flynn/bootstrap -json -min-hosts=%d /etc/manifest.json", inst.IP(), c.ControllerDomain, c.ControllerKey, len(c.instances), ) cmdErr = inst.Run(command, attempts, wr, os.Stderr) wr.Close() }() // grab the controller tls pin from the bootstrap output var cert controllerCert dec := json.NewDecoder(rd) for { var msg bootstrapMsg if err := dec.Decode(&msg); err == io.EOF { break } else if err != nil { return fmt.Errorf("failed to parse bootstrap JSON output: %s", err) } c.log("bootstrap ===>", msg.Id, msg.State) if msg.State == "error" { c.log(msg) } if msg.Id == "controller-cert" && msg.State == "done" { json.Unmarshal(msg.Data, &cert) } } if cmdErr != nil { return cmdErr } if cert.Pin == "" { return errors.New("could not determine controller cert from bootstrap output") } c.ControllerPin = cert.Pin // grab the router IP from discoverd discoverd.Connect(inst.IP() + ":1111") set, err := discoverd.NewServiceSet("router-api") if err != nil { return fmt.Errorf("could not detect router ip: %s", err) } defer set.Close() leader := set.Leader() if leader == nil { return errors.New("could not detect router ip: no router-api leader") } if err = setLocalDNS(c.ControllerDomain, leader.Host); err != nil { return fmt.Errorf("could not set router DNS entry: %s", err) } return nil }
func (s *CLISuite) TestReleaseDelete(t *c.C) { // create an app and release it twice r := s.newGitRepo(t, "http") app := "release-delete-" + random.String(8) t.Assert(r.flynn("create", app), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) t.Assert(r.git("commit", "--allow-empty", "--message", "empty commit"), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) // get the releases client := s.controllerClient(t) releases, err := client.AppReleaseList(app) t.Assert(err, c.IsNil) t.Assert(releases, c.HasLen, 2) // check the current release cannot be deleted res := r.flynn("release", "delete", "--yes", releases[0].ID) t.Assert(res, c.Not(Succeeds)) t.Assert(res.Output, c.Equals, "validation_error: cannot delete current app release\n") // associate the initial release with another app otherApp := &ct.App{Name: "release-delete-" + random.String(8)} t.Assert(client.CreateApp(otherApp), c.IsNil) t.Assert(client.PutFormation(&ct.Formation{AppID: otherApp.ID, ReleaseID: releases[1].ID}), c.IsNil) // check deleting the initial release just deletes the formation res = r.flynn("release", "delete", "--yes", releases[1].ID) t.Assert(res, Succeeds) t.Assert(res.Output, c.Equals, "Release scaled down for app but not fully deleted (still associated with 1 other apps)\n") // check the slug artifact still exists slugArtifact, err := client.GetArtifact(releases[1].ArtifactIDs[1]) t.Assert(err, c.IsNil) s.assertURI(t, slugArtifact.URI, http.StatusOK) slugLayerURL := slugArtifact.LayerURL(slugArtifact.Manifest().Rootfs[0].Layers[0]) s.assertURI(t, slugLayerURL, http.StatusOK) // check the inital release can now be deleted res = r.flynn("-a", otherApp.ID, "release", "delete", "--yes", releases[1].ID) t.Assert(res, Succeeds) t.Assert(res.Output, c.Equals, fmt.Sprintf("Deleted release %s (deleted 2 files)\n", releases[1].ID)) // check the slug artifact was deleted _, err = client.GetArtifact(slugArtifact.ID) t.Assert(err, c.Equals, controller.ErrNotFound) s.assertURI(t, slugArtifact.URI, http.StatusNotFound) s.assertURI(t, slugLayerURL, http.StatusNotFound) // check the image artifact was not deleted (since it is shared between both releases) _, err = client.GetArtifact(releases[1].ArtifactIDs[0]) t.Assert(err, c.IsNil) }
func (s *BasicSuite) TestBasic(t *c.C) { name := random.String(30) t.Assert(s.Flynn("create", name), Outputs, fmt.Sprintf("Created %s\n", name)) push := s.Git("push", "flynn", "master") t.Assert(push, OutputContains, "Node.js app detected") t.Assert(push, OutputContains, "Downloading and installing node") t.Assert(push, OutputContains, "Installing dependencies") t.Assert(push, OutputContains, "Procfile declares types -> web") t.Assert(push, OutputContains, "Creating release") t.Assert(push, OutputContains, "Application deployed") t.Assert(push, OutputContains, "* [new branch] master -> master") t.Assert(s.Flynn("scale", "web=3"), Succeeds) newRoute := s.Flynn("route-add-http", random.String(32)+".dev") t.Assert(newRoute, Succeeds) t.Assert(s.Flynn("routes"), OutputContains, strings.TrimSpace(newRoute.Output)) // use Attempts to give the processes time to start if err := Attempts.Run(func() error { ps := s.Flynn("ps") if ps.Err != nil { return ps.Err } psLines := strings.Split(strings.TrimSpace(ps.Output), "\n") if len(psLines) != 4 { return fmt.Errorf("Expected 4 ps lines, got %d", len(psLines)) } for _, l := range psLines[1:] { idType := regexp.MustCompile(`\s+`).Split(l, 2) if idType[1] != "web" { return fmt.Errorf("Expected web type, got %s", idType[1]) } log := s.Flynn("log", idType[0]) if !strings.Contains(log.Output, "Listening on ") { return fmt.Errorf("Expected \"%s\" to contain \"Listening on \"", log.Output) } } return nil }); err != nil { t.Error(err) } // Make HTTP requests }
func (s *CLISuite) TestRoute(t *c.C) { app := s.newCliTestApp(t) defer app.cleanup() // The router API does not currently give us a "read your own writes" // guarantee, so we must retry a few times if we don't get the expected // result. assertRouteContains := func(str string, contained bool) { var res *CmdResult attempt.Strategy{ Total: 10 * time.Second, Delay: 500 * time.Millisecond, }.Run(func() error { res = app.flynn("route") if contained == strings.Contains(res.Output, str) { return nil } return errors.New("unexpected output") }) if contained { t.Assert(res, SuccessfulOutputContains, str) } else { t.Assert(res, c.Not(SuccessfulOutputContains), str) } } // flynn route add http route := random.String(32) + ".dev" newRoute := app.flynn("route", "add", "http", "--sticky", route) t.Assert(newRoute, Succeeds) routeID := strings.TrimSpace(newRoute.Output) assertRouteContains(routeID, true) // ensure sticky flag is set routes, err := s.controllerClient(t).RouteList(app.name) t.Assert(err, c.IsNil) var found bool for _, r := range routes { if fmt.Sprintf("%s/%s", r.Type, r.ID) != routeID { continue } t.Assert(r.Sticky, c.Equals, true) found = true } t.Assert(found, c.Equals, true, c.Commentf("didn't find route")) // flynn route remove t.Assert(app.flynn("route", "remove", routeID), Succeeds) assertRouteContains(routeID, false) // flynn route add tcp tcpRoute := app.flynn("route", "add", "tcp") t.Assert(tcpRoute, Succeeds) routeID = strings.Split(tcpRoute.Output, " ")[0] assertRouteContains(routeID, true) // flynn route remove t.Assert(app.flynn("route", "remove", routeID), Succeeds) assertRouteContains(routeID, false) }
func (ZpoolTests) TestProviderAutomaticFileVdevZpoolCreation(c *C) { dataset := "testpool-dinosaur" // don't actually use ioutil.Tempfile; // we want to exerise the path where the file doesn't exist. backingFilePath := fmt.Sprintf("/tmp/zfs-%s", random.String(12)) defer os.Remove(backingFilePath) provider, err := NewProvider(&ProviderConfig{ DatasetName: dataset, Make: &MakeDev{ BackingFilename: backingFilePath, Size: one_gig, }, }) defer func() { pool, _ := gzfs.GetZpool(dataset) if pool != nil { pool.Destroy() } }() c.Assert(err, IsNil) c.Assert(provider, NotNil) // also, we shouldn't get any '/testpool' dir at root _, err = os.Stat(dataset) c.Assert(err, NotNil) c.Assert(os.IsNotExist(err), Equals, true) }
func (s *S) TestFormationStreamingInterrupted(c *C) { before := time.Now() appRepo := NewAppRepo(s.hc.db, os.Getenv("DEFAULT_ROUTE_DOMAIN"), s.hc.rc) releaseRepo := NewReleaseRepo(s.hc.db) artifactRepo := NewArtifactRepo(s.hc.db) formationRepo := NewFormationRepo(s.hc.db, appRepo, releaseRepo, artifactRepo) artifact := &ct.Artifact{Type: "docker", URI: fmt.Sprintf("https://example.com/%s", random.String(8))} c.Assert(artifactRepo.Add(artifact), IsNil) release := &ct.Release{ArtifactID: artifact.ID} c.Assert(releaseRepo.Add(release), IsNil) app := &ct.App{Name: "streamtest-interrupted"} c.Assert(appRepo.Add(app), IsNil) formation := &ct.Formation{ReleaseID: release.ID, AppID: app.ID} c.Assert(formationRepo.Add(formation), IsNil) ch := make(chan *ct.ExpandedFormation) updated := make(chan struct{}) _, err := formationRepo.Subscribe(ch, before, updated) c.Assert(err, IsNil) // simulate scenario where we have not completed `sendUpdatedSince` but the channel for a subscription // is closed, by example due to an error listening on table `formations` that triggered `unsubscribeAll`. formationRepo.unsubscribeAll() // wait until `sendUpdateSince` finishes at which point it will not longer send to the (now closed) channel. <-updated }
func New(bc BootConfig, out io.Writer) *Cluster { return &Cluster{ ID: random.String(8), bc: bc, out: out, } }
func (t *TapManager) NewTap(uid, gid int) (*Tap, error) { tap := &Tap{Name: "flynntap." + random.String(5), bridge: t.bridge} if err := createTap(tap.Name, uid, gid); err != nil { return nil, err } var err error tap.IP, err = t.bridge.alloc.RequestIP(t.bridge.ipNet, nil) if err != nil { tap.Close() return nil, err } iface, err := net.InterfaceByName(tap.Name) if err != nil { tap.Close() return nil, err } if err := netlink.NetworkLinkUp(iface); err != nil { tap.Close() return nil, err } if err := netlink.AddToBridge(iface, t.bridge.iface); err != nil { tap.Close() return nil, err } return tap, nil }
func testApp(s *CLISuite, t *c.C, remote string) { app := s.newGitRepo(t, "") name := random.String(30) flynnRemote := fmt.Sprintf("%s\tssh://git@%s/%s.git (push)", remote, s.clusterConf(t).GitHost, name) if remote == "flynn" { t.Assert(app.flynn("create", "-y", name), Outputs, fmt.Sprintf("Created %s\n", name)) } else { t.Assert(app.flynn("create", "-r", remote, "-y", name), Outputs, fmt.Sprintf("Created %s\n", name)) } t.Assert(app.flynn("apps"), SuccessfulOutputContains, name) t.Assert(app.flynn("-c", "default", "apps"), SuccessfulOutputContains, name) if remote == "" { t.Assert(app.git("remote", "-v"), c.Not(SuccessfulOutputContains), flynnRemote) } else { t.Assert(app.git("remote", "-v"), SuccessfulOutputContains, flynnRemote) } // make sure flynn components are listed t.Assert(app.flynn("apps"), SuccessfulOutputContains, "router") t.Assert(app.flynn("-c", "default", "apps"), SuccessfulOutputContains, "router") // flynn delete if remote == "flynn" { t.Assert(app.flynn("delete", "--yes"), Succeeds) } else { if remote == "" { t.Assert(app.flynn("-a", name, "delete", "--yes", "-r", remote), Succeeds) } else { t.Assert(app.flynn("delete", "--yes", "-r", remote), Succeeds) } } t.Assert(app.git("remote", "-v"), c.Not(SuccessfulOutputContains), flynnRemote) }
/* Make an 'ish' application on the given host, returning it when it has registered readiness with discoverd. User will want to defer cmd.Kill() to clean up. */ func makeIshApp(cluster *cluster.Client, h *cluster.Host, dc *discoverd.Client, extraConfig host.ContainerConfig) (*exec.Cmd, *discoverd.Instance, error) { // pick a unique string to use as service name so this works with concurrent tests. serviceName := "ish-service-" + random.String(6) // run a job that accepts tcp connections and performs tasks we ask of it in its container cmd := exec.JobUsingCluster(cluster, exec.DockerImage(imageURIs["test-apps"]), &host.Job{ Config: host.ContainerConfig{ Args: []string{"/bin/ish"}, Ports: []host.Port{{Proto: "tcp"}}, Env: map[string]string{ "NAME": serviceName, }, }.Merge(extraConfig), }) cmd.HostID = h.ID() if err := cmd.Start(); err != nil { return nil, nil, err } // wait for the job to heartbeat and return its address services, err := dc.Instances(serviceName, time.Second*100) if err != nil { cmd.Kill() return nil, nil, err } if len(services) != 1 { cmd.Kill() return nil, nil, fmt.Errorf("test setup: expected exactly one service instance, got %d", len(services)) } return cmd, services[0], nil }
func (s *CLISuite) TestReleaseRollback(t *c.C) { // create an app and release it r := s.newGitRepo(t, "http") app := "release-rollback-" + random.String(8) t.Assert(r.flynn("create", app), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) // check that rollback fails when there's only a single release res := r.flynn("release", "rollback", "--yes") t.Assert(res, c.Not(Succeeds)) // create a second release t.Assert(r.git("commit", "--allow-empty", "--message", "empty commit"), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) // get the releases client := s.controllerClient(t) releases, err := client.AppReleaseList(app) t.Assert(err, c.IsNil) t.Assert(releases, c.HasLen, 2) // rollback to the second release res = r.flynn("release", "rollback", "--yes") t.Assert(res, Succeeds) // revert rollback res = r.flynn("release", "rollback", "--yes", releases[0].ID) t.Assert(res, Succeeds) // check that attempting to rollback to the current release fails res = r.flynn("release", "rollback", "--yes", releases[0].ID) t.Assert(res, c.Not(Succeeds)) }
func (s *ControllerSuite) TestRouteEvents(t *c.C) { app := "app-route-events-" + random.String(8) client := s.controllerClient(t) // create and push app r := s.newGitRepo(t, "http") t.Assert(r.flynn("create", app), Succeeds) t.Assert(r.flynn("key", "add", r.ssh.Pub), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) // wait for it to start service := app + "-web" _, err := s.discoverdClient(t).Instances(service, 10*time.Second) t.Assert(err, c.IsNil) // stream events events := make(chan *ct.Event) stream, err := client.StreamEvents(controller.StreamEventsOptions{ AppID: app, ObjectTypes: []ct.EventType{ct.EventTypeRoute, ct.EventTypeRouteDeletion}, Past: true, }, events) t.Assert(err, c.IsNil) defer stream.Close() assertEventType := func(typ ct.EventType) { select { case event, ok := <-events: t.Assert(ok, c.Equals, true) t.Assert(event.ObjectType, c.Equals, typ, c.Commentf("event: %#v", event)) case <-time.After(30 * time.Second): t.Assert(true, c.Equals, false, c.Commentf("timed out waiting for %s event", string(typ))) } } // default app route assertEventType(ct.EventTypeRoute) // create some routes routes := []string{"baz.example.com"} for _, route := range routes { t.Assert(r.flynn("route", "add", "http", route), Succeeds) assertEventType(ct.EventTypeRoute) } routeList, err := client.RouteList(app) t.Assert(err, c.IsNil) numRoutes := len(routes) + 1 // includes default app route t.Assert(routeList, c.HasLen, numRoutes) // delete app cmd := r.flynn("delete", "--yes") t.Assert(cmd, Succeeds) // check route deletion event assertEventType(ct.EventTypeRouteDeletion) }
func newBuild(commit, description string, merge bool) *Build { now := time.Now() return &Build{ Id: now.Format("20060102150405") + "-" + random.String(8), CreatedAt: &now, Commit: commit, Description: description, Merge: merge, } }
func (s *S) createTestArtifact(c *C, in *ct.Artifact) *ct.Artifact { if in.Type == "" { in.Type = "docker" } if in.URI == "" { in.URI = fmt.Sprintf("https://example.com/%s", random.String(8)) } c.Assert(s.c.CreateArtifact(in), IsNil) return in }
func (s *CLISuite) TestProvider(t *c.C) { t.Assert(s.flynn(t, "provider"), SuccessfulOutputContains, "postgres") // flynn provider add testProvider := "test-provider" + random.String(8) testProviderUrl := "http://testprovider.discoverd" cmd := s.flynn(t, "provider", "add", testProvider, testProviderUrl) t.Assert(cmd, Outputs, fmt.Sprintf("Created provider %s.\n", testProvider)) t.Assert(s.flynn(t, "provider"), SuccessfulOutputContains, testProvider) }
func (s *CLISuite) TestDeploy(t *c.C) { // create and push app r := s.newGitRepo(t, "http") t.Assert(r.flynn("create", "deploy-"+random.String(8)), Succeeds) t.Assert(r.git("push", "flynn", "master"), Succeeds) deploy := r.flynn("deployment") t.Assert(deploy, Succeeds) t.Assert(deploy.Output, Matches, "complete") }
func (r *Runner) save(b *Build) error { if b.Id == "" { b.Id = b.CreatedAt.Format("20060102150405") + "-" + random.String(8) } return r.db.Update(func(tx *bolt.Tx) error { val, err := json.Marshal(b) if err != nil { return err } return tx.Bucket(dbBucket).Put([]byte(b.Id), val) }) }
func (ZpoolTests) TestOrphanedZpoolFileAdoption(c *C) { dataset := "testpool-bananagram" backingFilePath := fmt.Sprintf("/tmp/zfs-%s", random.String(12)) defer os.Remove(backingFilePath) provider, err := NewProvider(&ProviderConfig{ DatasetName: dataset, Make: &MakeDev{ BackingFilename: backingFilePath, Size: one_gig, }, }) defer func() { pool, _ := gzfs.GetZpool(dataset) if pool != nil { pool.Destroy() } }() c.Assert(err, IsNil) c.Assert(provider, NotNil) // add a dataset to this zpool, so we can check for it on the flip side markerDatasetName := path.Join(dataset, "testfs") _, err = gzfs.CreateFilesystem(markerDatasetName, nil) c.Assert(err, IsNil) // do a 'zpool export' // this roughly approximates what we see after a host reboot // (though host reboots may leave it in an even more unclean state than this) err = exec.Command("zpool", "export", "-f", dataset).Run() c.Assert(err, IsNil) // sanity check that our test is doing the right thing: zpool forgot about these _, err = gzfs.GetDataset(dataset) c.Assert(err, NotNil) _, err = gzfs.GetDataset(markerDatasetName) c.Assert(err, NotNil) // if we create another provider with the same file vdev path, it should // pick up that file again without wrecking the dataset provider, err = NewProvider(&ProviderConfig{ DatasetName: dataset, Make: &MakeDev{ BackingFilename: backingFilePath, Size: one_gig, }, }) c.Assert(err, IsNil) c.Assert(provider, NotNil) _, err = gzfs.GetDataset(markerDatasetName) c.Assert(err, IsNil) }
func (s *S) createTestArtifact(c *C, in *ct.Artifact) *ct.Artifact { if in.Type == "" { in.Type = ct.ArtifactTypeFlynn in.RawManifest = ct.ImageManifest{ Type: ct.ImageManifestTypeV1, }.RawManifest() } if in.URI == "" { in.URI = fmt.Sprintf("https://example.com/%s", random.String(8)) } c.Assert(s.c.CreateArtifact(in), IsNil) return in }
func parseEnviron() map[string]string { env := os.Environ() res := make(map[string]string, len(env)) for _, v := range env { kv := strings.SplitN(v, "=", 2) res[kv[0]] = kv[1] } if _, ok := res["ETCD_NAME"]; !ok { res["ETCD_NAME"] = random.String(8) } return res }
func (s *CLISuite) TestRemote(t *c.C) { remoteApp := "remote-" + random.String(8) customRemote := random.String(8) r := s.newGitRepoWithoutTrace(t, "http") // create app without remote t.Assert(r.flynn("create", remoteApp, "--remote", `""`), Succeeds) // ensure no remotes exist t.Assert(r.git("remote").Output, c.Equals, "\"\"\n") // create the default remote t.Assert(r.flynn("-a", remoteApp, "remote", "add"), Succeeds) // ensure the default remote exists t.Assert(r.git("remote", "show", "flynn"), Succeeds) // now delete it t.Assert(r.git("remote", "rm", "flynn"), Succeeds) // ensure no remotes exist t.Assert(r.git("remote").Output, c.Equals, "\"\"\n") // create a custom remote t.Assert(r.flynn("-a", remoteApp, "remote", "add", customRemote), Succeeds) // ensure the custom remote exists t.Assert(r.git("remote", "show", customRemote), Succeeds) }
func (c *Cluster) setup() error { if _, err := os.Stat(c.bc.Kernel); os.IsNotExist(err) { return fmt.Errorf("cluster: not a kernel file: %s", c.bc.Kernel) } if c.bridge == nil { var err error name := "flynnbr." + random.String(5) c.logf("creating network bridge %s\n", name) c.bridge, err = createBridge(name, c.bc.Network, c.bc.NatIface) if err != nil { return fmt.Errorf("could not create network bridge: %s", err) } } c.vm = NewVMManager(c.bridge) return nil }
// https://github.com/flynn/flynn/issues/2257 func (s *ControllerSuite) TestResourceProvisionRecreatedApp(t *c.C) { app := "app-recreate-" + random.String(8) client := s.controllerClient(t) // create, delete, and recreate app r := s.newGitRepo(t, "http") t.Assert(r.flynn("create", app), Succeeds) t.Assert(r.flynn("delete", "--yes"), Succeeds) t.Assert(r.flynn("create", app), Succeeds) // provision resource t.Assert(r.flynn("resource", "add", "postgres"), Succeeds) resources, err := client.AppResourceList(app) t.Assert(err, c.IsNil) t.Assert(resources, c.HasLen, 1) }
func NewLog(l *lumberjack.Logger) *Log { if l == nil { l = &lumberjack.Logger{} } if l.MaxSize == 0 { l.MaxSize = 100 // megabytes } if l.Filename == "" { l.Filename = path.Join(os.TempDir(), random.String(16)+".log") } l.Rotate() // force creating a log file straight away log := &Log{ l: l, closed: make(chan struct{}), } return log }
func (r *Runner) save(b *Build) error { if b.Id == "" { b.Id = random.String(8) } return r.db.Update(func(tx *bolt.Tx) error { bkt := tx.Bucket([]byte("pending-builds")) if b.State == "pending" { val, err := json.Marshal(b) if err != nil { return err } return bkt.Put([]byte(b.Id), val) } else { return bkt.Delete([]byte(b.Id)) } }) }
func (s *TempZpool) SetUpTest(c *C) { if s.IDstring == "" { s.IDstring = random.String(12) } // Set up a new provider with a zpool that will be destroyed on teardown s.ZpoolVdevFilePath = fmt.Sprintf("/tmp/flynn-test-zpool-%s.vdev", s.IDstring) s.ZpoolName = fmt.Sprintf("flynn-test-zpool-%s", s.IDstring) var err error s.VolProv, err = NewProvider(&ProviderConfig{ DatasetName: s.ZpoolName, Make: &MakeDev{ BackingFilename: s.ZpoolVdevFilePath, Size: int64(math.Pow(2, float64(30))), }, }) c.Assert(err, IsNil) }
func (v *VMManager) NewInstance(c *VMConfig) (*Instance, error) { var err error inst := &Instance{ID: random.String(8), VMConfig: c} if c.Kernel == "" { c.Kernel = "vmlinuz" } if c.Out == nil { c.Out, err = os.Create("flynn-" + inst.ID + ".log") if err != nil { return nil, err } } inst.tap, err = v.taps.NewTap(c.User, c.Group) if err != nil { return nil, err } inst.IP = inst.tap.RemoteIP.String() return inst, nil }