func main() { // Other packages define flags, and they need parsing here. kingpin.Parse() logger := logging.NewLogger(logrus.Fields{}) configPath := os.Getenv("CONFIG_PATH") if configPath == "" { logger.NoFields().Fatalln("No CONFIG_PATH variable was given") } preparerConfig, err := preparer.LoadConfig(configPath) if err != nil { logger.WithError(err).Fatalln("could not load preparer config") } err = param.Parse(preparerConfig.Params) if err != nil { logger.WithError(err).Fatalln("invalid parameter") } statusServer, err := preparer.NewStatusServer(preparerConfig.StatusPort, preparerConfig.StatusSocket, &logger) if err == preparer.NoServerConfigured { logger.NoFields().Warningln("No status port or socket provided, no status server configured") } else if err != nil { logger.WithError(err).Fatalln("Could not start status server") } else { go statusServer.Serve() defer statusServer.Close() } prep, err := preparer.New(preparerConfig, logger) if err != nil { logger.WithError(err).Fatalln("Could not initialize preparer") } defer prep.Close() logger.WithFields(logrus.Fields{ "starting": true, "node_name": preparerConfig.NodeName, "consul": preparerConfig.ConsulAddress, "hooks_dir": preparerConfig.HooksDirectory, "status_port": preparerConfig.StatusPort, "auth_type": preparerConfig.Auth["type"], "keyring": preparerConfig.Auth["keyring"], "version": version.VERSION, }).Infoln("Preparer started successfully") quitMainUpdate := make(chan struct{}) var quitChans []chan struct{} // Install the latest hooks before any pods are processed err = prep.InstallHooks() if err != nil { logger.WithError(err).Fatalln("Could not do initial hook installation") } go prep.WatchForPodManifestsForNode(quitMainUpdate) if prep.PodProcessReporter != nil { quitPodProcessReporter := make(chan struct{}) quitChans = append(quitChans, quitPodProcessReporter) go prep.PodProcessReporter.Run(quitPodProcessReporter) } // Launch health checking watch. This watch tracks health of // all pods on this host and writes the information to consul quitMonitorPodHealth := make(chan struct{}) var wgHealth sync.WaitGroup wgHealth.Add(1) go func() { defer wgHealth.Done() watch.MonitorPodHealth(preparerConfig, &logger, quitMonitorPodHealth) }() waitForTermination(logger, quitMainUpdate, quitChans) // The preparer should continue to report app health during a shutdown, so terminate // the health monitor last. close(quitMonitorPodHealth) wgHealth.Wait() logger.NoFields().Infoln("Terminating") }
func main() { // 1. Generate pod for preparer in this code version (`rake artifact:prepare`) // 2. Locate manifests for preparer pod, premade consul pod // 3. Execute bootstrap with premade consul pod and preparer pod // 4. Deploy hello pod manifest by pushing to intent store // 5. Verify that hello is running (listen to syslog? verify Runit PIDs? Both?) // list of services running on integration test host services := []string{"p2-preparer", "hello"} tempdir, err := ioutil.TempDir("", "single-node-check") log.Printf("Putting test manifests in %s\n", tempdir) if err != nil { log.Fatalln("Could not create temp directory, bailing") } preparerManifest, err := generatePreparerPod(tempdir) if err != nil { log.Fatalf("Could not generate preparer pod: %s\n", err) } config, err := preparer.LoadConfig(preparerManifest) if err != nil { log.Fatalf("could not unmarshal config: %s\n", err) } consulManifest, err := getConsulManifest(tempdir) if err != nil { log.Fatalf("Could not generate consul pod: %s\n", err) } signedPreparerManifest, err := signManifest(preparerManifest, tempdir) if err != nil { log.Fatalf("Could not sign preparer manifest: %s\n", err) } signedConsulManifest, err := signManifest(consulManifest, tempdir) if err != nil { log.Fatalf("Could not sign consul manifest: %s\n", err) } fmt.Println("Executing bootstrap") err = executeBootstrap(signedPreparerManifest, signedConsulManifest) if err != nil { log.Fatalf("Could not execute bootstrap: %s", err) } // Wait a bit for preparer's http server to be ready err = waitForStatus(preparerStatusPort, "preparer", 10*time.Second) if err != nil { log.Fatalf("Couldn't check preparer status: %s", err) } err = scheduleUserCreationHook(tempdir) if err != nil { log.Fatalf("Couldn't schedule the user creation hook: %s", err) } err = postHelloManifest(tempdir) if err != nil { log.Fatalf("Could not generate hello pod: %s\n", err) } err = verifyHelloRunning() if err != nil { log.Fatalf("Couldn't get hello running: %s", err) } err = verifyHealthChecks(config, services) if err != nil { log.Fatalf("Could not get health check info from consul: %s", err) } }
func main() { // 1. Generate pod for preparer in this code version (`rake artifact:prepare`) // 2. Locate manifests for preparer pod, premade consul pod // 3. Execute bootstrap with premade consul pod and preparer pod // 4. Deploy p2-rctl-server pod with p2-schedule // 5. Schedule a hello pod manifest with a replication controller // 6. Verify that p2-rctl-server is running by checking health. // 7. Verify that hello is running by checking health. Monitor using // written pod label queries. // list of services running on integration test host services := []string{"p2-preparer", "hello"} tempdir, err := ioutil.TempDir("", "single-node-check") log.Printf("Putting test manifests in %s\n", tempdir) if err != nil { log.Fatalln("Could not create temp directory, bailing") } preparerManifest, err := generatePreparerPod(tempdir) if err != nil { log.Fatalf("Could not generate preparer pod: %s\n", err) } config, err := preparer.LoadConfig(preparerManifest) if err != nil { log.Fatalf("could not unmarshal config: %s\n", err) } consulManifest, err := getConsulManifest(tempdir) if err != nil { log.Fatalf("Could not generate consul pod: %s\n", err) } signedPreparerManifest, err := signManifest(preparerManifest, tempdir) if err != nil { log.Fatalf("Could not sign preparer manifest: %s\n", err) } signedConsulManifest, err := signManifest(consulManifest, tempdir) if err != nil { log.Fatalf("Could not sign consul manifest: %s\n", err) } fmt.Println("Executing bootstrap") err = executeBootstrap(signedPreparerManifest, signedConsulManifest) if err != nil { log.Fatalf("Could not execute bootstrap: %s", err) } // Wait a bit for preparer's http server to be ready err = waitForStatus(preparerStatusPort, "preparer", 10*time.Second) if err != nil { log.Fatalf("Couldn't check preparer status: %s", err) } err = scheduleUserCreationHook(tempdir) if err != nil { log.Fatalf("Couldn't schedule the user creation hook: %s", err) } err = scheduleRCTLServer(tempdir) if err != nil { log.Fatalf("Could not schedule RCTL server: %s", err) } rcID, err := createHelloReplicationController(tempdir) if err != nil { log.Fatalf("Could not create hello pod / rc: %s\n", err) } log.Printf("Created RC #%s for hello\n", rcID) err = waitForPodLabeledWithRC(klabels.Everything().Add(rc.RCIDLabel, klabels.EqualsOperator, []string{rcID.String()}), rcID) if err != nil { log.Fatalf("Failed waiting for pods labeled with the given RC: %v", err) } err = verifyHelloRunning() if err != nil { log.Fatalf("Couldn't get hello running: %s", err) } err = verifyHealthChecks(config, services) if err != nil { log.Fatalf("Could not get health check info from consul: %s", err) } }
func main() { // 1. Generate pod for preparer in this code version (`rake artifact:prepare`) // 2. Locate manifests for preparer pod, premade consul pod // 3. Execute bootstrap with premade consul pod and preparer pod // 4. Delete all pods from the pod store (uuid pods). This allows the same vagrant VM to be used // between tests // 5. Deploy p2-rctl-server pod with p2-schedule // 6. Schedule a hello pod manifest with a replication controller // 7. Schedule a hello pod as a "uuid pod" // 8. Verify that p2-rctl-server is running by checking health. // 9. Verify that the RC-deployed hello is running by checking health. // Monitor using written pod label queries. // 10. Verify that the uuid hello pod is running by curling its HTTP port. // Health is not checked for uuid pods so checking health cannot be used. // list of services running on integration test host services := []string{"p2-preparer", "hello"} tempdir, err := ioutil.TempDir("", "single-node-check") log.Printf("Putting test manifests in %s\n", tempdir) if err != nil { log.Fatalln("Could not create temp directory, bailing") } userHookManifest, err := userCreationHookManifest(tempdir) if err != nil { log.Fatalf("Couldn't schedule the user creation hook: %s", err) } preparerManifest, err := generatePreparerPod(tempdir, userHookManifest) if err != nil { log.Fatalf("Could not generate preparer pod: %s\n", err) } config, err := preparer.LoadConfig(preparerManifest) if err != nil { log.Fatalf("could not unmarshal config: %s\n", err) } consulManifest, err := getConsulManifest(tempdir) if err != nil { log.Fatalf("Could not generate consul pod: %s\n", err) } signedPreparerManifest, err := signManifest(preparerManifest, tempdir) if err != nil { log.Fatalf("Could not sign preparer manifest: %s\n", err) } signedConsulManifest, err := signManifest(consulManifest, tempdir) if err != nil { log.Fatalf("Could not sign consul manifest: %s\n", err) } fmt.Println("Executing bootstrap") err = executeBootstrap(signedPreparerManifest, signedConsulManifest) if err != nil { log.Fatalf("Could not execute bootstrap: %s\n%s", err, targetLogs()) } // Wait a bit for preparer's http server to be ready err = waitForStatus(preparerStatusPort, "preparer", 10*time.Second) if err != nil { log.Fatalf("Couldn't check preparer status: %s", err) } consulClient := kp.NewConsulClient(kp.Options{}) // Get all the pod unique keys so we can unschedule them all keys, _, err := consulClient.KV().Keys(podstore.PodTree+"/", "", nil) if err != nil { log.Fatalf("Could not fetch pod keys to remove from store at beginning of test: %s", err) } podStore := podstore.NewConsul(consulClient.KV()) for _, key := range keys { keyParts := strings.Split(key, "/") err = podStore.Unschedule(types.PodUniqueKey(keyParts[len(keyParts)-1])) if err != nil { log.Fatalf("Could not unschedule pod %s from consul: %s", keyParts[len(keyParts)-1], err) } } err = scheduleRCTLServer(tempdir) if err != nil { log.Fatalf("Could not schedule RCTL server: %s", err) } // Now we're going to test some conditions that each take non-negligible amount of time to verify. // We'll spin up a goroutine for each "test" which either closes the error channel, or passes an error. type testCase struct { testName string errCh chan error logger logging.Logger } var testCases []testCase // Test that a "legacy" pod installed by an RC comes up correctly and has health reported legacyTest := make(chan error) verifyLegacyPodLogger := logging.DefaultLogger.SubLogger(logrus.Fields{ "test_case": "verifyLegacyPod", }) go verifyLegacyPod(legacyTest, tempdir, config, services, verifyLegacyPodLogger) testCases = append(testCases, testCase{ testName: "verifyLegacyPod", errCh: legacyTest, logger: verifyLegacyPodLogger, }) // Test that a "uuid" pod installed by p2-schedule comes up correctly uuidTest := make(chan error) verifyUUIDPodLogger := logging.DefaultLogger.SubLogger(logrus.Fields{ "test_case": "verifyUUIDPod", }) testCases = append(testCases, testCase{ testName: "verifyUUIDPod", errCh: uuidTest, logger: verifyUUIDPodLogger, }) go verifyUUIDPod(uuidTest, tempdir, verifyUUIDPodLogger) // Test that exit information for a process started by a pod is properly recorded in consul. processExitTest := make(chan error) verifyProcessExitLogger := logging.DefaultLogger.SubLogger(logrus.Fields{ "test_case": "verifyProcessExit", }) go verifyProcessExit(processExitTest, tempdir, verifyProcessExitLogger) testCases = append(testCases, testCase{ testName: "verifyProcessResult", errCh: processExitTest, logger: verifyProcessExitLogger, }) for _, t := range testCases { select { case err, ok := <-t.errCh: if err != nil { t.logger.Fatal(err) } if ok { t.logger.Fatal("Error channel not closed") } case <-time.After(1 * time.Minute): t.logger.Fatal("Timed out waiting for a result") } t.logger.Infoln("Success!") } }
func main() { // Other packages define flags, and they need parsing here. kingpin.Parse() logger := logging.NewLogger(logrus.Fields{}) configPath := os.Getenv("CONFIG_PATH") if configPath == "" { logger.NoFields().Fatalln("No CONFIG_PATH variable was given") } preparerConfig, err := preparer.LoadConfig(configPath) if err != nil { logger.WithError(err).Fatalln("could not load preparer config") } err = param.Parse(preparerConfig.Params) if err != nil { logger.WithError(err).Fatalln("invalid parameter") } statusServer, err := preparer.NewStatusServer(preparerConfig.StatusPort, preparerConfig.StatusSocket, &logger) if err == preparer.NoServerConfigured { logger.NoFields().Warningln("No status port or socket provided, no status server configured") } else if err != nil { logger.WithError(err).Fatalln("Could not start status server") } else { go statusServer.Serve() defer statusServer.Close() } prep, err := preparer.New(preparerConfig, logger) if err != nil { logger.WithError(err).Fatalln("Could not initialize preparer") } defer prep.Close() logger.WithFields(logrus.Fields{ "starting": true, "node_name": preparerConfig.NodeName, "consul": preparerConfig.ConsulAddress, "hooks_dir": preparerConfig.HooksDirectory, "status_port": preparerConfig.StatusPort, "auth_type": preparerConfig.Auth["type"], "keyring": preparerConfig.Auth["keyring"], "version": version.VERSION, }).Infoln("Preparer started successfully") quitMainUpdate := make(chan struct{}) quitHookUpdate := make(chan struct{}) quitChans := []chan struct{}{quitHookUpdate} // Guarantee that hooks are synced before any other pods are processed err = prep.SyncHooksOnce() if err != nil { logger.WithError(err).Fatalln("Could not do initial sync of hooks") } go prep.WatchForPodManifestsForNode(quitMainUpdate) go prep.WatchForHooks(quitHookUpdate) // Launch health checking watch. This watch tracks health of // all pods on this host and writes the information to consul quitMonitorPodHealth := make(chan struct{}) go watch.MonitorPodHealth(preparerConfig, &logger, quitMonitorPodHealth) quitChans = append(quitChans, quitMonitorPodHealth) waitForTermination(logger, quitMainUpdate, quitChans) logger.NoFields().Infoln("Terminating") }