github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/common/apps/apps.go (about)

     1  // Copyright 2015 The rkt Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //+build linux
    16  
    17  package apps
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema"
    23  	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
    24  )
    25  
    26  type App struct {
    27  	Image  string         // the image reference as supplied by the user on the cli
    28  	Args   []string       // any arguments the user supplied for this app
    29  	Asc    string         // signature file override for image verification (if fetching occurs)
    30  	Exec   string         // exec override for image
    31  	Mounts []schema.Mount // mounts for this app (superseding any mounts in rktApps.mounts of same MountPoint)
    32  
    33  	// TODO(jonboulle): These images are partially-populated hashes, this should be clarified.
    34  	ImageID types.Hash // resolved image identifier
    35  }
    36  
    37  type Apps struct {
    38  	apps    []App
    39  	Mounts  []schema.Mount // global mounts applied to all apps
    40  	Volumes []types.Volume // volumes available to all apps
    41  }
    42  
    43  // Reset creates a new slice for al.apps, needed by tests
    44  func (al *Apps) Reset() {
    45  	al.apps = make([]App, 0)
    46  }
    47  
    48  // Count returns the number of apps in al
    49  func (al *Apps) Count() int {
    50  	return len(al.apps)
    51  }
    52  
    53  // Create creates a new app in al and returns a pointer to it
    54  func (al *Apps) Create(img string) {
    55  	al.apps = append(al.apps, App{Image: img})
    56  }
    57  
    58  // Last returns a pointer to the top app in al
    59  func (al *Apps) Last() *App {
    60  	if len(al.apps) == 0 {
    61  		return nil
    62  	}
    63  	return &al.apps[len(al.apps)-1]
    64  }
    65  
    66  // Validate validates al for things like referential integrity of mounts<->volumes.
    67  func (al *Apps) Validate() error {
    68  	vs := map[types.ACName]struct{}{}
    69  	for _, v := range al.Volumes {
    70  		vs[v.Name] = struct{}{}
    71  	}
    72  
    73  	f := func(mnts []schema.Mount) error {
    74  		for _, m := range mnts {
    75  			if _, ok := vs[m.Volume]; !ok {
    76  				return fmt.Errorf("dangling mount point %q: volume %q not found", m.Path, m.Volume)
    77  			}
    78  		}
    79  		return nil
    80  	}
    81  
    82  	if err := f(al.Mounts); err != nil {
    83  		return err
    84  	}
    85  
    86  	err := al.Walk(func(app *App) error {
    87  		return f(app.Mounts)
    88  	})
    89  
    90  	/* TODO(vc): in debug/verbose mode say something about unused volumes? */
    91  	return err
    92  }
    93  
    94  // Walk iterates on al.apps calling f for each app
    95  // walking stops if f returns an error, the error is simply returned
    96  func (al *Apps) Walk(f func(*App) error) error {
    97  	for i, _ := range al.apps {
    98  		// XXX(vc): note we supply f() with a pointer to the app instance in al.apps to enable modification by f()
    99  		if err := f(&al.apps[i]); err != nil {
   100  			return err
   101  		}
   102  	}
   103  	return nil
   104  }
   105  
   106  // these convenience functions just return typed lists containing just the named member
   107  // TODO(vc): these probably go away when we just pass Apps to stage0
   108  
   109  // GetImages returns a list of the images in al, one per app.
   110  // The order reflects the app order in al.
   111  func (al *Apps) GetImages() []string {
   112  	var il []string
   113  	for _, a := range al.apps {
   114  		il = append(il, a.Image)
   115  	}
   116  	return il
   117  }
   118  
   119  // GetArgs returns a list of lists of arguments in al, one list of args per app.
   120  // The order reflects the app order in al.
   121  func (al *Apps) GetArgs() [][]string {
   122  	var aal [][]string
   123  	for _, a := range al.apps {
   124  		aal = append(aal, a.Args)
   125  	}
   126  	return aal
   127  }
   128  
   129  // GetImageIDs returns a list of the imageIDs in al, one per app.
   130  // The order reflects the app order in al.
   131  func (al *Apps) GetImageIDs() []types.Hash {
   132  	var hl []types.Hash
   133  	for _, a := range al.apps {
   134  		hl = append(hl, a.ImageID)
   135  	}
   136  	return hl
   137  }