github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/rkt/image_render.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 package main 16 17 import ( 18 "encoding/json" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 23 "github.com/coreos/rkt/pkg/fileutil" 24 "github.com/coreos/rkt/pkg/uid" 25 "github.com/coreos/rkt/store" 26 27 "github.com/coreos/rkt/Godeps/_workspace/src/github.com/spf13/cobra" 28 ) 29 30 var ( 31 cmdImageRender = &cobra.Command{ 32 Use: "render IMAGE OUTPUT_DIR", 33 Short: "Render a stored image to a directory with all its dependencies", 34 Long: `IMAGE should be a string referencing an image: either a hash or an image name.`, 35 Run: runWrapper(runImageRender), 36 } 37 flagRenderRootfsOnly bool 38 flagRenderOverwrite bool 39 ) 40 41 func init() { 42 cmdImage.AddCommand(cmdImageRender) 43 cmdImageRender.Flags().BoolVar(&flagRenderRootfsOnly, "rootfs-only", false, "render rootfs only") 44 cmdImageRender.Flags().BoolVar(&flagRenderOverwrite, "overwrite", false, "overwrite output directory") 45 } 46 47 func runImageRender(cmd *cobra.Command, args []string) (exit int) { 48 if len(args) != 2 { 49 cmd.Usage() 50 return 1 51 } 52 outputDir := args[1] 53 54 s, err := store.NewStore(globalFlags.Dir) 55 if err != nil { 56 stderr("image render: cannot open store: %v", err) 57 return 1 58 } 59 60 key, err := getStoreKeyFromAppOrHash(s, args[0]) 61 if err != nil { 62 stderr("image render: %v", err) 63 return 1 64 } 65 66 id, err := s.RenderTreeStore(key, false) 67 if err != nil { 68 stderr("image render: error rendering ACI: %v", err) 69 return 1 70 } 71 if err := s.CheckTreeStore(id); err != nil { 72 stderr("image render: warning: tree cache is in a bad state. Rebuilding...") 73 var err error 74 if id, err = s.RenderTreeStore(key, true); err != nil { 75 stderr("image render: error rendering ACI: %v", err) 76 return 1 77 } 78 } 79 80 if _, err := os.Stat(outputDir); err == nil { 81 if !flagRenderOverwrite { 82 stderr("image render: output directory exists (try --overwrite)") 83 return 1 84 } 85 86 // don't allow the user to delete the root filesystem by mistake 87 if outputDir == "/" { 88 stderr("image extract: this would delete your root filesystem. Refusing.") 89 return 1 90 } 91 92 if err := os.RemoveAll(outputDir); err != nil { 93 stderr("image render: error removing existing output dir: %v", err) 94 return 1 95 } 96 } 97 rootfsOutDir := outputDir 98 if !flagRenderRootfsOnly { 99 if err := os.MkdirAll(outputDir, 0755); err != nil { 100 stderr("image render: error creating output directory: %v", err) 101 return 1 102 } 103 rootfsOutDir = filepath.Join(rootfsOutDir, "rootfs") 104 105 manifest, err := s.GetImageManifest(key) 106 if err != nil { 107 stderr("image render: error getting manifest: %v", err) 108 return 1 109 } 110 111 mb, err := json.Marshal(manifest) 112 if err != nil { 113 stderr("image render: error marshalling image manifest: %v", err) 114 return 1 115 } 116 117 if err := ioutil.WriteFile(filepath.Join(outputDir, "manifest"), mb, 0700); err != nil { 118 stderr("image render: error writing image manifest: %v", err) 119 return 1 120 } 121 } 122 123 cachedTreePath := s.GetTreeStoreRootFS(id) 124 if err := fileutil.CopyTree(cachedTreePath, rootfsOutDir, uid.NewBlankUidRange()); err != nil { 125 stderr("image render: error copying ACI rootfs: %v", err) 126 return 1 127 } 128 129 return 0 130 }