mirror of
https://github.com/clearlinux/rkt.git
synced 2026-08-19 05:27:23 +00:00
rkt: turn rkt/app.go into the package common/apps
Step towards supplying stage0 with Apps rather than a bunch of lists...
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//+build linux
|
||||
|
||||
package apps
|
||||
|
||||
import (
|
||||
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
Image string // the image reference as supplied by the user on the cli
|
||||
Args []string // any arguments the user supplied for this app
|
||||
Asc string // signature file override for image verification (if fetching occurs)
|
||||
|
||||
// TODO(jonboulle): These images are partially-populated hashes, this should be clarified.
|
||||
ImageID types.Hash // resolved image identifier
|
||||
}
|
||||
|
||||
type Apps struct {
|
||||
apps []App
|
||||
}
|
||||
|
||||
// Reset creates a new slice for al.apps, needed by tests
|
||||
func (al *Apps) Reset() {
|
||||
al.apps = make([]App, 0)
|
||||
}
|
||||
|
||||
// Count returns the number of apps in al
|
||||
func (al *Apps) Count() int {
|
||||
return len(al.apps)
|
||||
}
|
||||
|
||||
// Create creates a new app in al and returns a pointer to it
|
||||
func (al *Apps) Create(img string) {
|
||||
al.apps = append(al.apps, App{Image: img})
|
||||
}
|
||||
|
||||
// Last returns a pointer to the top app in al
|
||||
func (al *Apps) Last() *App {
|
||||
if len(al.apps) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &al.apps[len(al.apps)-1]
|
||||
}
|
||||
|
||||
// Walk iterates on al.apps calling f for each app
|
||||
// walking stops if f returns an error, the error is simply returned
|
||||
func (al *Apps) Walk(f func(*App) error) error {
|
||||
for i, _ := range al.apps {
|
||||
// XXX(vc): note we supply f() with a pointer to the app instance in al.apps to enable modification by f()
|
||||
if err := f(&al.apps[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// these convenience functions just return typed lists containing just the named member
|
||||
// TODO(vc): these probably go away when we just pass Apps to stage0
|
||||
|
||||
// GetImages returns a list of the images in al, one per app.
|
||||
// The order reflects the app order in al.
|
||||
func (al *Apps) GetImages() []string {
|
||||
il := []string{}
|
||||
for _, a := range al.apps {
|
||||
il = append(il, a.Image)
|
||||
}
|
||||
return il
|
||||
}
|
||||
|
||||
// GetArgs returns a list of lists of arguments in al, one list of args per app.
|
||||
// The order reflects the app order in al.
|
||||
func (al *Apps) GetArgs() [][]string {
|
||||
aal := [][]string{}
|
||||
for _, a := range al.apps {
|
||||
aal = append(aal, a.Args)
|
||||
}
|
||||
return aal
|
||||
}
|
||||
|
||||
// GetImageIDs returns a list of the imageIDs in al, one per app.
|
||||
// The order reflects the app order in al.
|
||||
func (al *Apps) GetImageIDs() []types.Hash {
|
||||
hl := []types.Hash{}
|
||||
for _, a := range al.apps {
|
||||
hl = append(hl, a.ImageID)
|
||||
}
|
||||
return hl
|
||||
}
|
||||
+16
-103
@@ -20,71 +20,18 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
|
||||
"github.com/coreos/rkt/common/apps"
|
||||
)
|
||||
|
||||
var (
|
||||
Apps rktApps // global apps
|
||||
rktApps apps.Apps // global used by run/prepare for representing the apps expressed via the cli
|
||||
)
|
||||
|
||||
type rktApp struct {
|
||||
image string // the image reference as supplied by the user on the cli
|
||||
args []string // any arguments the user supplied for this app
|
||||
asc string // signature file override for image verification (if fetching occurs)
|
||||
|
||||
imageID types.Hash // resolved image identifier
|
||||
}
|
||||
|
||||
// this needs to be a struct for the type defines like appAsc to work correctly with receivers
|
||||
type rktApps struct {
|
||||
apps []rktApp
|
||||
}
|
||||
|
||||
// reset creates a new slice for al.apps, needed by tests
|
||||
func (al *rktApps) reset() {
|
||||
al.apps = make([]rktApp, 0)
|
||||
}
|
||||
|
||||
// count returns the number of apps in al
|
||||
func (al *rktApps) count() int {
|
||||
return len(al.apps)
|
||||
}
|
||||
|
||||
// create creates a new app in al and returns a pointer to it
|
||||
func (al *rktApps) create(img string) {
|
||||
al.apps = append(al.apps, rktApp{image: img})
|
||||
}
|
||||
|
||||
// last returns a pointer to the top app in al
|
||||
func (al *rktApps) last() *rktApp {
|
||||
if len(al.apps) == 0 {
|
||||
return nil
|
||||
} else {
|
||||
return &al.apps[len(al.apps)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// appendArg appends another argument onto the app
|
||||
func (a *rktApp) appendArg(arg string) {
|
||||
a.args = append(a.args, arg)
|
||||
}
|
||||
|
||||
// sets the ascii-armored signature file path for the app
|
||||
func (a *rktApp) setAsc(asc string) {
|
||||
a.asc = asc
|
||||
}
|
||||
|
||||
// gets the ascii-armored signature file path for the app
|
||||
func (a *rktApp) getAsc() string {
|
||||
return a.asc
|
||||
}
|
||||
|
||||
// parseApps looks through the args for support of per-app argument lists delimited with "--" and "---".
|
||||
// Between per-app argument lists flags.Parse() is called using the supplied FlagSet.
|
||||
// Anything not consumed by flags.Parse() and not found to be a per-app argument list is treated as an image.
|
||||
func (al *rktApps) parse(args []string, flags *flag.FlagSet) error {
|
||||
al.reset()
|
||||
nAppsLastAppArgs := al.count()
|
||||
func parseApps(al *apps.Apps, args []string, flags *flag.FlagSet) error {
|
||||
nAppsLastAppArgs := al.Count()
|
||||
|
||||
// valid args here may either be:
|
||||
// not-"--"; flags handled by *flags or an image specifier
|
||||
@@ -101,7 +48,8 @@ func (al *rktApps) parse(args []string, flags *flag.FlagSet) error {
|
||||
inAppArgs = false
|
||||
default:
|
||||
// keep appending to this app's args
|
||||
al.last().appendArg(a)
|
||||
app := al.Last()
|
||||
app.Args = append(app.Args, a)
|
||||
}
|
||||
} else {
|
||||
switch a {
|
||||
@@ -110,13 +58,13 @@ func (al *rktApps) parse(args []string, flags *flag.FlagSet) error {
|
||||
inAppArgs = true
|
||||
|
||||
// catch some likely mistakes
|
||||
if nAppsLastAppArgs == al.count() {
|
||||
if al.count() == 0 {
|
||||
if nAppsLastAppArgs == al.Count() {
|
||||
if al.Count() == 0 {
|
||||
return fmt.Errorf("an image is required before any app arguments")
|
||||
}
|
||||
return fmt.Errorf("only one set of app arguments allowed per image")
|
||||
}
|
||||
nAppsLastAppArgs = al.count()
|
||||
nAppsLastAppArgs = al.Count()
|
||||
case "---":
|
||||
// ignore triple dashes since they aren't images
|
||||
// TODO(vc): I don't think ignoring this is appropriate, probably should error; it implies malformed argv.
|
||||
@@ -139,7 +87,7 @@ func (al *rktApps) parse(args []string, flags *flag.FlagSet) error {
|
||||
i += nInterFlags - 1 // - 1 because of i++
|
||||
} else {
|
||||
// flags.Parse() didn't want this arg, treat as image
|
||||
al.create(a)
|
||||
al.Create(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,65 +96,30 @@ func (al *rktApps) parse(args []string, flags *flag.FlagSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// these convenience functions just return typed lists containing just the named member
|
||||
// TODO(vc): these probably go away when we just pass rktApps to stage0
|
||||
|
||||
// getImages returns a list of the images in al, one per app.
|
||||
// The order reflects the app order in al.
|
||||
func (al *rktApps) getImages() []string {
|
||||
il := []string{}
|
||||
for _, a := range al.apps {
|
||||
il = append(il, a.image)
|
||||
}
|
||||
return il
|
||||
}
|
||||
|
||||
// getArgs returns a list of lists of arguments in al, one list of args per app.
|
||||
// The order reflects the app order in al.
|
||||
func (al *rktApps) getArgs() [][]string {
|
||||
aal := [][]string{}
|
||||
for _, a := range al.apps {
|
||||
aal = append(aal, a.args)
|
||||
}
|
||||
return aal
|
||||
}
|
||||
|
||||
// getImageIDs returns a list of the imageIDs in al, one per app.
|
||||
// The order reflects the app order in al.
|
||||
func (al *rktApps) getImageIDs() []types.Hash {
|
||||
hl := []types.Hash{}
|
||||
for _, a := range al.apps {
|
||||
hl = append(hl, a.imageID)
|
||||
}
|
||||
return hl
|
||||
}
|
||||
|
||||
// Value interface implementations for the various per-app fields we provide flags for
|
||||
|
||||
// appAsc is for aci --signature overrides
|
||||
type appAsc rktApps
|
||||
type appAsc apps.Apps
|
||||
|
||||
func (al *appAsc) Set(s string) error {
|
||||
app := (*rktApps)(al).last()
|
||||
app := (*apps.Apps)(al).Last()
|
||||
if app == nil {
|
||||
return fmt.Errorf("--signature must follow an image")
|
||||
}
|
||||
|
||||
if app.getAsc() != "" {
|
||||
if app.Asc != "" {
|
||||
return fmt.Errorf("--signature specified multiple times for the same image")
|
||||
}
|
||||
|
||||
app.setAsc(s)
|
||||
app.Asc = s
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (al *appAsc) String() string {
|
||||
app := (*rktApps)(al).last()
|
||||
app := (*apps.Apps)(al).Last()
|
||||
if app == nil {
|
||||
return ""
|
||||
}
|
||||
return app.getAsc()
|
||||
return app.Asc
|
||||
}
|
||||
|
||||
// TODO(vc): --mount, --set-env, etc.
|
||||
@@ -62,9 +62,10 @@ func TestParseAppArgs(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
err := Apps.parse(strings.Split(tt.in, " "), flags)
|
||||
ga := Apps.getArgs()
|
||||
gi := Apps.getImages()
|
||||
rktApps.Reset()
|
||||
err := parseApps(&rktApps, strings.Split(tt.in, " "), flags)
|
||||
ga := rktApps.GetArgs()
|
||||
gi := rktApps.GetImages()
|
||||
if gerr := (err != nil); gerr != tt.werr {
|
||||
t.Errorf("#%d: err==%v, want errstate %t", i, err, tt.werr)
|
||||
}
|
||||
+7
-7
@@ -21,20 +21,20 @@ import (
|
||||
|
||||
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
|
||||
"github.com/coreos/rkt/cas"
|
||||
"github.com/coreos/rkt/common/apps"
|
||||
"github.com/coreos/rkt/pkg/keystore"
|
||||
)
|
||||
|
||||
// findImages uses findImage to attain a list of image hashes using discovery if necessary
|
||||
func (al *rktApps) findImages(ds *cas.Store, ks *keystore.Keystore) error {
|
||||
for _, app := range al.apps {
|
||||
h, err := findImage(app.image, app.asc, ds, ks, true)
|
||||
func findImages(al *apps.Apps, ds *cas.Store, ks *keystore.Keystore) error {
|
||||
return al.Walk(func(app *apps.App) error {
|
||||
h, err := findImage(app.Image, app.Asc, ds, ks, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app.imageID = *h
|
||||
}
|
||||
|
||||
return nil
|
||||
app.ImageID = *h
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// findImage will recognize a ACI hash and use that, import a local file, use
|
||||
|
||||
+5
-5
@@ -67,12 +67,12 @@ func runPrepare(args []string) (exit int) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = Apps.parse(args, &prepareFlags); err != nil {
|
||||
if err = parseApps(&rktApps, args, &prepareFlags); err != nil {
|
||||
stderr("prepare: error parsing app image arguments: %v", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
if Apps.count() < 1 {
|
||||
if rktApps.Count() < 1 {
|
||||
stderr("prepare: Must provide at least one image")
|
||||
return 1
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func runPrepare(args []string) (exit int) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := Apps.findImages(ds, getKeystore()); err != nil {
|
||||
if err := findImages(&rktApps, ds, getKeystore()); err != nil {
|
||||
stderr("%v", err)
|
||||
return 1
|
||||
}
|
||||
@@ -114,9 +114,9 @@ func runPrepare(args []string) (exit int) {
|
||||
Debug: globalFlags.Debug,
|
||||
Stage1Image: *s1img,
|
||||
UUID: p.uuid,
|
||||
Images: Apps.getImageIDs(),
|
||||
Images: rktApps.GetImageIDs(),
|
||||
},
|
||||
ExecAppends: Apps.getArgs(),
|
||||
ExecAppends: rktApps.GetArgs(),
|
||||
Volumes: []types.Volume(flagVolumes),
|
||||
InheritEnv: flagInheritEnv,
|
||||
ExplicitEnv: flagExplicitEnv.Strings(),
|
||||
|
||||
+6
-6
@@ -78,7 +78,7 @@ func init() {
|
||||
runFlags.BoolVar(&flagNoOverlay, "no-overlay", false, "disable overlay filesystem")
|
||||
runFlags.Var(&flagExplicitEnv, "set-env", "an environment variable to set for apps in the form name=value")
|
||||
runFlags.BoolVar(&flagInteractive, "interactive", false, "run pod interactively")
|
||||
runFlags.Var((*appAsc)(&Apps), "signature", "local signature file to use in validating the preceding image")
|
||||
runFlags.Var((*appAsc)(&rktApps), "signature", "local signature file to use in validating the preceding image")
|
||||
flagVolumes = volumeList{}
|
||||
}
|
||||
|
||||
@@ -97,13 +97,13 @@ func runRun(args []string) (exit int) {
|
||||
}
|
||||
}
|
||||
|
||||
err := Apps.parse(args, &runFlags)
|
||||
err := parseApps(&rktApps, args, &runFlags)
|
||||
if err != nil {
|
||||
stderr("run: error parsing app image arguments: %v", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
if Apps.count() < 1 {
|
||||
if rktApps.Count() < 1 {
|
||||
stderr("run: must provide at least one image")
|
||||
return 1
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func runRun(args []string) (exit int) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := Apps.findImages(ds, getKeystore()); err != nil {
|
||||
if err := findImages(&rktApps, ds, getKeystore()); err != nil {
|
||||
stderr("%v", err)
|
||||
return 1
|
||||
}
|
||||
@@ -135,13 +135,13 @@ func runRun(args []string) (exit int) {
|
||||
Store: ds,
|
||||
Stage1Image: *s1img,
|
||||
UUID: p.uuid,
|
||||
Images: Apps.getImageIDs(),
|
||||
Images: rktApps.GetImageIDs(),
|
||||
Debug: globalFlags.Debug,
|
||||
}
|
||||
|
||||
pcfg := stage0.PrepareConfig{
|
||||
CommonConfig: cfg,
|
||||
ExecAppends: Apps.getArgs(),
|
||||
ExecAppends: rktApps.GetArgs(),
|
||||
Volumes: []types.Volume(flagVolumes),
|
||||
InheritEnv: flagInheritEnv,
|
||||
ExplicitEnv: flagExplicitEnv.Strings(),
|
||||
|
||||
Reference in New Issue
Block a user