github.com/masahide/goansible@v0.0.0-20160116054156-01eac649e9f2/package/apt/apt.go (about)

     1  package apt
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/masahide/goansible"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"regexp"
    10  	"time"
    11  )
    12  
    13  type Apt struct {
    14  	Pkg       string `goansible:"pkg"`
    15  	State     string `goansible:"state" enum:"present,install,absent,remove"`
    16  	Cache     bool   `goansible:"update_cache"`
    17  	CacheTime string `goansible:"cache_time"`
    18  	Dry       bool   `goansible:"dryrun"`
    19  }
    20  
    21  var installed = regexp.MustCompile(`Installed: ([^\n]+)`)
    22  var candidate = regexp.MustCompile(`Candidate: ([^\n]+)`)
    23  
    24  func (a *Apt) Run(env *goansible.CommandEnv) (*goansible.Result, error) {
    25  	state := a.State
    26  	if state == "" {
    27  		state = "present"
    28  	}
    29  
    30  	if a.Cache {
    31  		home, err := goansible.HomeDir()
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  
    36  		checkFile := filepath.Join(home, ".goansible", "apt-cache-timestamp")
    37  
    38  		runUpdate := true
    39  
    40  		if a.CacheTime != "" {
    41  			fi, err := os.Stat(checkFile)
    42  			if err == nil {
    43  				dur, err := time.ParseDuration(a.CacheTime)
    44  				if err != nil {
    45  					return nil, fmt.Errorf("cache_time was not in the proper format")
    46  				}
    47  
    48  				runUpdate = time.Now().After(fi.ModTime().Add(dur))
    49  			}
    50  		}
    51  
    52  		if runUpdate {
    53  			_, err := goansible.RunCommand(env, "apt-get", "update")
    54  			if err != nil {
    55  				return nil, err
    56  			}
    57  			ioutil.WriteFile(checkFile, []byte(``), 0666)
    58  		}
    59  	}
    60  
    61  	if a.Pkg == "" {
    62  		simp := goansible.NewResult(true)
    63  		simp.Add("cache", "updated")
    64  
    65  		return simp, nil
    66  	}
    67  
    68  	out, err := goansible.RunCommand(env, "apt-cache", "policy", a.Pkg)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	res := installed.FindSubmatch(out.Stdout)
    74  	if res == nil {
    75  		return nil, fmt.Errorf("No package '%s' available", a.Pkg)
    76  	}
    77  
    78  	curVer := string(res[1])
    79  	if curVer == "(none)" {
    80  		curVer = ""
    81  	}
    82  
    83  	res = candidate.FindSubmatch(out.Stdout)
    84  	if res == nil {
    85  		return nil, fmt.Errorf("Error parsing apt-cache output")
    86  	}
    87  
    88  	canVer := string(res[1])
    89  
    90  	if state == "absent" {
    91  		rd := goansible.ResultData{}
    92  
    93  		if curVer == "" {
    94  			return goansible.WrapResult(false, rd), nil
    95  		}
    96  
    97  		rd.Set("removed", curVer)
    98  
    99  		_, err = goansible.RunCommand(env, "apt-get", "remove", "-y", a.Pkg)
   100  
   101  		if err != nil {
   102  			return nil, err
   103  		}
   104  
   105  		return goansible.WrapResult(true, rd), nil
   106  	}
   107  
   108  	rd := goansible.ResultData{}
   109  	rd.Set("installed", curVer)
   110  	rd.Set("candidate", canVer)
   111  
   112  	if state == "present" && curVer == canVer {
   113  		return goansible.WrapResult(false, rd), nil
   114  	}
   115  
   116  	if a.Dry {
   117  		rd.Set("dryrun", true)
   118  		return goansible.WrapResult(true, rd), nil
   119  	}
   120  
   121  	e := append(os.Environ(), "DEBIAN_FRONTEND=noninteractive", "DEBIAN_PRIORITY=critical")
   122  
   123  	_, err = goansible.RunCommandInEnv(env, e, "apt-get", "install", "-y", a.Pkg)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  
   128  	rd.Set("installed", canVer)
   129  
   130  	return goansible.WrapResult(true, rd), nil
   131  }
   132  
   133  func init() {
   134  	goansible.RegisterCommand("apt", &Apt{})
   135  }