github.com/mfpierre/corectl@v0.5.6/list.go (about)

     1  // Copyright 2015 - António Meireles  <antonio.meireles@reformi.st>
     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  
    16  package main
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"path"
    24  	"path/filepath"
    25  	"time"
    26  
    27  	"github.com/blang/semver"
    28  	"github.com/spf13/cobra"
    29  )
    30  
    31  var (
    32  	lsCmd = &cobra.Command{
    33  		Use:     "ls",
    34  		Aliases: []string{"list"},
    35  		Short:   "Lists locally available CoreOS images",
    36  		PreRunE: defaultPreRunE,
    37  		RunE:    lsCommand,
    38  	}
    39  )
    40  
    41  func lsCommand(cmd *cobra.Command, args []string) (err error) {
    42  	var (
    43  		channels []string
    44  		local    map[string]semver.Versions
    45  	)
    46  	if local, err = localImages(); err != nil {
    47  		return
    48  	}
    49  
    50  	if engine.rawArgs.GetBool("all") {
    51  		channels = DefaultChannels
    52  	} else {
    53  		channels = append(channels,
    54  			normalizeChannelName(engine.rawArgs.GetString("channel")))
    55  	}
    56  	if engine.rawArgs.GetBool("json") {
    57  		var pp []byte
    58  		if len(channels) == 1 {
    59  			if pp, err = json.MarshalIndent(
    60  				local[normalizeChannelName(engine.rawArgs.GetString("channel"))],
    61  				"", "    "); err != nil {
    62  				return
    63  			}
    64  		} else {
    65  			if pp, err = json.MarshalIndent(local, "", "    "); err != nil {
    66  				return
    67  			}
    68  		}
    69  		fmt.Println(string(pp))
    70  		return
    71  	}
    72  	fmt.Println("locally available images")
    73  	for _, i := range channels {
    74  		var header bool
    75  		for _, d := range local[i] {
    76  			if !header {
    77  				fmt.Printf("  - %s channel \n", i)
    78  				header = true
    79  			}
    80  			fmt.Println("    -", d.String())
    81  		}
    82  	}
    83  	return
    84  }
    85  
    86  func init() {
    87  	lsCmd.Flags().String("channel", "alpha", "CoreOS channel")
    88  	lsCmd.Flags().BoolP("all", "a", false, "browses all channels")
    89  	lsCmd.Flags().BoolP("json", "j", false,
    90  		"outputs in JSON for easy 3rd party integration")
    91  	RootCmd.AddCommand(lsCmd)
    92  }
    93  
    94  func localImages() (local map[string]semver.Versions, err error) {
    95  	var (
    96  		files    []os.FileInfo
    97  		f        os.FileInfo
    98  		channel  string
    99  		stamp, _ = time.Parse("2006-01-02T15:04:05MST", LatestImageBreackage)
   100  	)
   101  	local = make(map[string]semver.Versions, 0)
   102  	for _, channel = range DefaultChannels {
   103  		if files, err = ioutil.ReadDir(filepath.Join(engine.imageDir,
   104  			channel)); err != nil {
   105  			return
   106  		}
   107  		var v semver.Versions
   108  		for _, f = range files {
   109  			if f.IsDir() {
   110  				ok := true
   111  				var ff string
   112  				for _, ff = range []string{"coreos_production_pxe.vmlinuz",
   113  					"coreos_production_pxe_image.cpio.gz"} {
   114  					if _, err = os.Stat(path.Join(engine.imageDir,
   115  						channel, f.Name(), ff)); err != nil {
   116  						ok = false
   117  						break
   118  					}
   119  				}
   120  				if ok && f.ModTime().After(stamp) {
   121  					var s semver.Version
   122  					if s, err = semver.Make(f.Name()); err != nil {
   123  						return
   124  					}
   125  					v = append(v, s)
   126  				} else {
   127  					// force rebuild if local image assembled before last time
   128  					// we changed its expcted format or something got missing
   129  					if err = os.RemoveAll(path.Join(engine.imageDir, channel,
   130  						f.Name(), ff)); err != nil {
   131  						return
   132  					}
   133  				}
   134  			}
   135  		}
   136  		semver.Sort(v)
   137  		local[channel] = v
   138  	}
   139  	return
   140  }