// Write servicebuilder *.yaml file and run servicebuilder, which will register runit services for this // pod. func (pod *Pod) buildRunitServices(launchables []launch.Launchable, newManifest manifest.Manifest) error { // if the service is new, building the runit services also starts them sbTemplate := make(map[string]runit.ServiceTemplate) for _, launchable := range launchables { executables, err := launchable.Executables(pod.ServiceBuilder) if err != nil { pod.logLaunchableError(launchable.ServiceID(), err, "Unable to list executables") continue } for _, executable := range executables { if _, ok := sbTemplate[executable.Service.Name]; ok { return util.Errorf("Duplicate executable %q for launchable %q", executable.Service.Name, launchable.ServiceID()) } sbTemplate[executable.Service.Name] = runit.ServiceTemplate{ Log: pod.LogExec, Run: executable.Exec, Finish: pod.FinishExecForLaunchable(launchable), } } } err := pod.ServiceBuilder.Activate(string(pod.Id), sbTemplate, newManifest.GetRestartPolicy()) if err != nil { return err } // as with the original servicebuilder, prune after creating // new services return pod.ServiceBuilder.Prune() }
func (pod *Pod) Launchables(manifest manifest.Manifest) ([]launch.Launchable, error) { launchableStanzas := manifest.GetLaunchableStanzas() launchables := make([]launch.Launchable, 0, len(launchableStanzas)) for _, launchableStanza := range launchableStanzas { launchable, err := pod.getLaunchable(launchableStanza, manifest.RunAsUser(), manifest.GetRestartPolicy()) if err != nil { return nil, err } launchables = append(launchables, launchable) } return launchables, nil }
func (pod *Pod) Verify(manifest manifest.Manifest, authPolicy auth.Policy) error { for _, stanza := range manifest.GetLaunchableStanzas() { if stanza.DigestLocation == "" { continue } launchable, err := pod.getLaunchable(stanza, manifest.RunAsUser(), manifest.GetRestartPolicy()) if err != nil { return err } digestLocationURL, err := url.Parse(stanza.DigestLocation) if err != nil { return util.Errorf("Couldn't parse digest location '%s' as a url: %s", stanza.DigestLocation, err) } digestSignatureLocationURL, err := url.Parse(stanza.DigestSignatureLocation) if err != nil { return util.Errorf("Couldn't parse digest signature location '%s' as a url: %s", stanza.DigestSignatureLocation, err) } // Retrieve the digest data launchableDigest, err := digest.ParseUris( uri.DefaultFetcher, digestLocationURL, digestSignatureLocationURL, ) if err != nil { return err } // Check that the digest is certified err = authPolicy.CheckDigest(launchableDigest) if err != nil { return err } // Check that the installed files match the digest err = launchableDigest.VerifyDir(launchable.InstallDir()) if err != nil { return err } } return nil }
// Install will ensure that executables for all required services are present on the host // machine and are set up to run. In the case of Hoist artifacts (which is the only format // supported currently, this will set up runit services.). func (pod *Pod) Install(manifest manifest.Manifest, verifier auth.ArtifactVerifier, artifactRegistry artifact.Registry) error { podHome := pod.home uid, gid, err := user.IDs(manifest.RunAsUser()) if err != nil { return util.Errorf("Could not determine pod UID/GID for %s: %s", manifest.RunAsUser(), err) } err = util.MkdirChownAll(podHome, uid, gid, 0755) if err != nil { return util.Errorf("Could not create pod home: %s", err) } launchables, err := pod.Launchables(manifest) if err != nil { return err } downloader := artifact.NewLocationDownloader(pod.Fetcher, verifier) for launchableID, stanza := range manifest.GetLaunchableStanzas() { // TODO: investigate passing in necessary fields to InstallDir() launchable, err := pod.getLaunchable(stanza, manifest.RunAsUser(), manifest.GetRestartPolicy()) if err != nil { pod.logLaunchableError(launchable.ServiceID(), err, "Unable to install launchable") return err } if launchable.Installed() { continue } launchableURL, verificationData, err := artifactRegistry.LocationDataForLaunchable(launchableID, stanza) if err != nil { pod.logLaunchableError(launchable.ServiceID(), err, "Unable to install launchable") return err } err = downloader.Download(launchableURL, verificationData, launchable.InstallDir(), manifest.RunAsUser()) if err != nil { pod.logLaunchableError(launchable.ServiceID(), err, "Unable to install launchable") _ = os.Remove(launchable.InstallDir()) return err } err = launchable.PostInstall() if err != nil { pod.logLaunchableError(launchable.ServiceID(), err, "Unable to install launchable") _ = os.Remove(launchable.InstallDir()) return err } } // we may need to write config files to a unique directory per pod version, depending on restart semantics. Need // to think about this more. err = pod.setupConfig(manifest, launchables) if err != nil { pod.logError(err, "Could not setup config") return util.Errorf("Could not setup config: %s", err) } pod.logInfo("Successfully installed") return nil }