func manifestMustEqual(expected, actual manifest.Manifest, t *testing.T) { actualSha, err := actual.SHA() Assert(t).IsNil(err, "should have gotten SHA from old manifest") expectedSha, err := expected.SHA() Assert(t).IsNil(err, "should have gotten SHA from known old manifest") manifestBytes, err := expected.Marshal() Assert(t).IsNil(err, "should have gotten bytes from manifest") actualBytes, err := actual.Marshal() Assert(t).IsNil(err, "should have gotten bytes from writtenOld") Assert(t).AreEqual(expectedSha, actualSha, fmt.Sprintf("known: \n\n%s\n\nactual:\n\n%s\n", string(manifestBytes), string(actualBytes))) }
// matches podstore.consulStore signature func (c Client) Schedule(manifest manifest.Manifest, node types.NodeName) (types.PodUniqueKey, error) { manifestBytes, err := manifest.Marshal() if err != nil { return "", util.Errorf("Could not marshal manifest: %s", err) } req := &podstore_protos.SchedulePodRequest{ NodeName: node.String(), Manifest: string(manifestBytes), } resp, err := c.client.SchedulePod(context.Background(), req) if err != nil { return "", util.Errorf("Could not schedule pod: %s", err) } return types.PodUniqueKey(resp.PodUniqueKey), nil }
func (c *consulStore) Schedule(manifest manifest.Manifest, node types.NodeName) (key types.PodUniqueKey, err error) { manifestBytes, err := manifest.Marshal() if err != nil { return "", err } podKey := types.NewPodUUID() podPath := computePodPath(podKey) intentIndexPath := computeIntentIndexPath(podKey, node) // Write the Pod to /pods/<key> pod := RawPod{ Manifest: string(manifestBytes), Node: node, } podBytes, err := json.Marshal(pod) if err != nil { return "", err } pair := &api.KVPair{ Key: podPath, Value: podBytes, } _, err = c.consulKV.Put(pair, nil) if err != nil { return "", consulutil.NewKVError("put", podPath, err) } // Now, write the secondary index to /intent/<node>/<key> index := PodIndex{ PodKey: podKey, } // NOTE: errors might happen after this point which means we've written // a pod to /pods and we haven't written the corresponding index. In // those cases, we do a single attempt to delete the main pod key. In // the event of a Consul outage it's likely that the cleanup will fail, // so there will be a pod with no secondary index. For that purpose, a // sweeper process is planned to remove pods for which there is no index. // TODO: use a transaction when we can rely upon consul 0.7 defer func() { if err != nil { _, _ = c.consulKV.Delete(podPath, nil) } }() indexBytes, err := json.Marshal(index) if err != nil { return "", util.Errorf("Could not marshal index as json: %s", err) } indexPair := &api.KVPair{ Key: intentIndexPath, Value: indexBytes, } _, err = c.consulKV.Put(indexPair, nil) if err != nil { return "", consulutil.NewKVError("put", intentIndexPath, err) } return podKey, nil }
func generatePreparerPod(workdir string, userHookManifest manifest.Manifest) (string, error) { // build the artifact from HEAD output, err := exec.Command("go", "build", "github.com/square/p2/bin/p2-preparer").CombinedOutput() if err != nil { return "", util.Errorf("Couldn't build preparer: %s\nOutput:\n%s", err, string(output)) } wd, _ := os.Getwd() hostname, err := os.Hostname() if err != nil { return "", util.Errorf("Couldn't get hostname: %s", err) } // the test number forces the pod manifest to change every test run. testNumber := fmt.Sprintf("test=%d", rand.Intn(2000000000)) cmd := exec.Command("p2-bin2pod", "--work-dir", workdir, "--id", "p2-preparer", "--config", fmt.Sprintf("node_name=%s", hostname), "--config", testNumber, wd+"/p2-preparer") prepBin2Pod, err := executeBin2Pod(cmd) if err != nil { return "", err } if err = signBuild(prepBin2Pod.TarPath); err != nil { return "", err } manifest, err := manifest.FromPath(prepBin2Pod.ManifestPath) if err != nil { return "", err } builder := manifest.GetBuilder() builder.SetID("p2-preparer") envExtractorPath, err := exec.Command("which", "p2-finish-env-extractor").CombinedOutput() if err != nil { return "", fmt.Errorf("Could not find p2-finish-env-extractor on PATH") } userCreationHookBytes, err := userHookManifest.Marshal() if err != nil { return "", util.Errorf("Couldn't marshal user hook manifest: %s", err) } err = builder.SetConfig(map[interface{}]interface{}{ "preparer": map[interface{}]interface{}{ "auth": map[string]string{ "type": "keyring", "keyring": util.From(runtime.Caller(0)).ExpandPath("pubring.gpg"), }, "artifact_auth": map[interface{}]interface{}{ "type": "build", "keyring": util.From(runtime.Caller(0)).ExpandPath("pubring.gpg"), }, "ca_file": filepath.Join(certpath, "cert.pem"), "cert_file": filepath.Join(certpath, "cert.pem"), "key_file": filepath.Join(certpath, "key.pem"), "status_port": preparerStatusPort, "process_result_reporter_config": map[string]string{ "sqlite_database_path": sqliteFinishDatabasePath, "environment_extractor_path": strings.TrimSpace(string(envExtractorPath)), "workspace_dir_path": "/data/pods/p2-preparer/tmp", }, "hooks_manifest": string(userCreationHookBytes), }, }) if err != nil { return "", err } builder.SetRunAsUser("root") builder.SetStatusPort(preparerStatusPort) builder.SetStatusHTTP(true) manifest = builder.GetManifest() manifestBytes, err := manifest.Marshal() if err != nil { return "", err } err = ioutil.WriteFile(prepBin2Pod.ManifestPath, manifestBytes, 0644) if err != nil { return "", err } return prepBin2Pod.ManifestPath, err }