<commit_before>// Copyright 2015 The Serulian Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package es5

// Note: nativenew is based on http://www.bennadel.com/blog/2291-invoking-a-native-javascript-constructor-using-call-or-apply.htm
// Note: toType is based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
// Note: uuid generation from https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript

// runtimeTemplate contains all the necessary code for wrapping generated modules into a complete Serulian
// runtime bundle.
const runtimeTemplate = `
this.Serulian = (function($global) {
  var $__currentScriptSrc = null;
  if (typeof document === 'object') {
    $__currentScriptSrc = document.currentScript.src;
  }

  $global.__serulian_internal = {
    'autoNominalWrap': function(k, v) {
      if (v == null) {
        return v;
      }

      var typeName = $t.toType(v);
      switch (typeName) {
        case 'object':
          if (k != '') {
            return $t.nominalwrap(v, $a.mapping($t.any));
          }
          break;

        case 'array':
          return $t.nominalwrap(v, $a.slice($t.any));

        case 'boolean':
          return $t.nominalwrap(v, $a.bool);

        case 'string':
          return $t.nominalwrap(v, $a.string);

        case 'number':
          if (Math.ceil(v) == v) {
            return $t.nominalwrap(v, $a.int);
          }

          return $t.nominalwrap(v, $a.float64);
      }

      return v;
    }
  };

  var $g = {};
  var $a = {};
  var $w = {};

  var $t = {
    'toType': function(obj) {
      return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
    },

    'any': new Function("return function any() {};")(),

    'cast': function(value, type) {
      // TODO: implement cast checking.
      return value
    },

    'uuid': function() {
        var buf = new Uint16Array(8);
        crypto.getRandomValues(buf);
        var S4 = function(num) {
            var ret = num.toString(16);
            while(ret.length < 4){
                ret = "0"+ret;
            }
            return ret;
        };
        return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    },

    'nativenew': function(type) {
      return function () {
        var newInstance = Object.create(type.prototype);
        newInstance = type.apply(newInstance, arguments) || newInstance;
        return newInstance;
      };
    },

    'nominalroot': function(instance) {
      if (instance.$wrapped) {
        return instance.$wrapped;
      }

      return instance;
    },

    'nominalwrap': function(instance, type) {
      return type.new($t.nominalroot(instance))
    },

    'nominalunwrap': function(instance) {
      return instance.$wrapped;
    },

    'workerwrap': function(methodId, f) {
      $w[methodId] = f;

      // If already inside a worker, return a function to execute asynchronously locally.
      if (!$__currentScriptSrc) {
        return function() {
          var promise = new Promise(function(resolve, reject) {
            $global.setTimeout(function() {
              f().then(function(value) {
                resolve(value);
              }).catch(function(value) {
                reject(value);
              });
            }, 0);
          });
          return promise;
        };
      }

      // Otherwise return a function to execute via a worker.
      return function() {
         var args = Array.prototype.slice.call(arguments);
         var token = $t.uuid();

         var promise = new Promise(function(resolve, reject) {
           var worker = new Worker($__currentScriptSrc + "?__serulian_async_token=" + token);
           worker.onmessage = function(e) {
              if (!e.isTrusted) {
                worker.terminate();
                return;
              }

              var data = e.data;
              if (data['token'] != token) {
                return;
              }

              if (data['result']) {
                resolve(data['result']);
              } else {
                reject(data['reject']);
              }

              worker.terminate();
           };

           worker.postMessage({
            'action': 'invoke',
            'arguments': args,
            'method': methodId,
            'token': token
           });
         });
         return promise;
      };
    },

    'property': function(getter, opt_setter) {
      var f = function() {
        if (arguments.length == 1) {
          return opt_setter.apply(this, arguments);
        } else {
          return getter.apply(this, arguments);
        }
      };

      f.$property = true;
      return f;
    },

    'dynamicaccess': function(obj, name) {
      if (obj == null || obj[name] == null) {
        return null;
      }

      var value = obj[name];
      if (typeof value == 'function' && value.$property) {
        return $promise.wrap(function() {
          return value.apply(obj, arguments);
        });
      }

      return value
    },

    'nullcompare': function(first, second) {
      return first == null ? second : first;
    },

  	'sm': function(caller) {
  		return {
        resources: {},
  			current: 0,
  			next: caller,

        pushr: function(value, name) {
          this.resources[name] = value;
        },

        popr: function(names) {
          var promises = [];

          for (var i = 0; i < arguments.length; ++i) {
            var name = arguments[i];
            if (this.resources[name]) {
              promises.push(this.resources[name].Release());
              delete this.resources[name];
            }
          }

          if (promises.length > 0) {
            return $promise.all(promises);
          } else {
            return $promise.resolve(null);
          }
        },

        popall: function() {
          for (var name in this.resources) {
            if (this.resources.hasOwnProperty(name)) {
              this.resources[name].Release();
            }
          }
        }
  		};
  	}
  };

  var $promise = {
  	'build': function(statemachine) {
  		return new Promise(function(resolve, reject) {
        statemachine.resolve = function(value) {
          statemachine.popall();
          statemachine.current = -1;
          resolve(value);
        };

        statemachine.reject = function(value) {
          statemachine.popall();
          statemachine.current = -1;
          reject(value);
        };

  			var continueFunc = function() {
  				if (statemachine.current < 0) {
  					return;
  				}

  				statemachine.next(callFunc);
			  };

        var callFunc = function() {
    			continueFunc();
          if (statemachine.current < 0) {
            statemachine.resolve(null);
          }
        };

        callFunc();
  		});
  	},

  	'all': function(promises) {
  		return Promise.all(promises);
  	},

  	'empty': function() {
  		return new Promise(function() {
  			resolve();
  		});
  	},

    'resolve': function(value) {
      return Promise.resolve(value);
    },

  	'wrap': function(func) {
  		return Promise.resolve(func());
  	},

    'translate': function(prom) {
       if (!prom.Then) {
         return prom;
       }

       return {
          'then': function() {
             return prom.Then.apply(prom, arguments);
          },
          'catch': function() {
             return prom.Catch.apply(prom, arguments);
          }
       };
    }
  };

  var moduleInits = [];

  var $module = function(name, creator) {
  	var module = {};

    var parts = name.split('.');
    var current = $g;
    for (var i = 0; i < parts.length - 1; ++i) {
      if (!current[parts[i]]) {
        current[parts[i]] = {};
      }
      current = current[parts[i]]
    }

    current[parts[parts.length - 1]] = module;

  	module.$init = function(cpromise) {
  	  moduleInits.push(cpromise);
  	};

    module.$newtypebuilder = function(kind) {
      return function(name, hasGenerics, alias, creator) {
        var buildType = function(n, args) {
          var tpe = new Function("return function " + n + "() {};")();
          creator.apply(tpe, args || []);

          if (kind == 'type') {
            tpe.prototype.toJSON = function() {
              return $t.nominalunwrap(this);
            };
          } else if (kind == 'struct') {
            // Stringify.
            tpe.prototype.Stringify = function(T) {
              var $this = this;
              return function() {
                // Special case JSON, as it uses an internal method.
                if (T == $a['$json']) {
                  return $promise.resolve(JSON.stringify($this.data));
                }

                return T.Get().then(function(resolved) {
                  return resolved.Stringify($t.any)($this.data);
                });
              };
            };

            // Parse.
            tpe.Parse = function(T) {
              return function(value) {
                // TODO: Validate the struct.

                // Special case JSON for performance, as it uses an internal method.
                if (T == $a['$json']) {
                  var created = new tpe();
                  created.data = JSON.parse($t.nominalunwrap(value));
                  return $promise.resolve(created);
                }

                return T.Get().then(function(resolved) {
                  return (resolved.Parse($t.any)(value)).then(function(parsed) {
                    var created = new tpe();
                    // TODO: *efficiently* unwrap internal nominal types.
                    created.data = JSON.parse(JSON.stringify($t.nominalunwrap(parsed)));
                    return $promise.resolve(created);
                  });
                });
              };
            };
          }

          return tpe;
        };

        if (hasGenerics) {
          module[name] = function(__genericargs) {
            var fullName = name;
            for (var i = 0; i < arguments.length; ++i) {
              fullName = fullName + '_' + arguments[i].name;
            }

            return buildType(fullName, arguments);
          };
        } else {
          module[name] = buildType(name);
        }

        if (alias) {
          $a[alias] = module[name];
        }
      };
    };

    module.$struct = module.$newtypebuilder('struct');
  	module.$class = module.$newtypebuilder('class');
  	module.$interface = module.$newtypebuilder('interface');
    module.$type = module.$newtypebuilder('type');

  	creator.call(module)
  };

  {{ range $idx, $kv := .Iter }}
  	{{ $kv.Value }}
  {{ end }}

  $g.executeWorkerMethod = function(token) {
    $global.onmessage = function(e) {
      if (!e.isTrusted) {
        $global.close();
        return;
      }

      var data = e.data;
      if (data['token'] != token) {
        throw Error('Invalid token')
        $global.close();
      }

      switch (data['action']) {
        case 'invoke':
          var methodId = data['method'];
          var arguments = data['arguments'];
          var method = $w[methodId];

          method.apply(null, arguments).then(function(result) {
            $global.postMessage({
              'result': result,
              'token': token
            });
            $global.close();
          }).catch(function(reject) {
            $global.postMessage({
              'reject': reject,
              'token': token
            });
            $global.close();
          });
          break
      }
    };
  };

  return $promise.all(moduleInits).then(function() {
  	return $g;
  });
})(this)

// Handle web-worker calls.
if (typeof importScripts === 'function') {
  var runWorker = function() {
    var search = location.search;
    if (!search || search[0] != '?') {
      return;
    }

    var searchPairs = search.substr(1).split('&')
    if (searchPairs.length < 1) {
      return;
    }

    for (var i = 0; i < searchPairs.length; ++i) {
      var pair = searchPairs[i].split('=');
      if (pair[0] == '__serulian_async_token') {
        this.Serulian.then(function(global) {
          global.executeWorkerMethod(pair[1]);
        });
        return;
      }
    }

    close();
  };
  runWorker();
}
`
<commit_msg>Throw uncatchable rejections<commit_after>// Copyright 2015 The Serulian Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package es5

// Note: nativenew is based on http://www.bennadel.com/blog/2291-invoking-a-native-javascript-constructor-using-call-or-apply.htm
// Note: toType is based on https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
// Note: uuid generation from https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript

// runtimeTemplate contains all the necessary code for wrapping generated modules into a complete Serulian
// runtime bundle.
const runtimeTemplate = `
this.Serulian = (function($global) {
  var $__currentScriptSrc = null;
  if (typeof document === 'object') {
    $__currentScriptSrc = document.currentScript.src;
  }

  $global.__serulian_internal = {
    'autoNominalWrap': function(k, v) {
      if (v == null) {
        return v;
      }

      var typeName = $t.toType(v);
      switch (typeName) {
        case 'object':
          if (k != '') {
            return $t.nominalwrap(v, $a.mapping($t.any));
          }
          break;

        case 'array':
          return $t.nominalwrap(v, $a.slice($t.any));

        case 'boolean':
          return $t.nominalwrap(v, $a.bool);

        case 'string':
          return $t.nominalwrap(v, $a.string);

        case 'number':
          if (Math.ceil(v) == v) {
            return $t.nominalwrap(v, $a.int);
          }

          return $t.nominalwrap(v, $a.float64);
      }

      return v;
    }
  };

  var $g = {};
  var $a = {};
  var $w = {};

  var $t = {
    'toType': function(obj) {
      return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
    },

    'any': new Function("return function any() {};")(),

    'cast': function(value, type) {
      // TODO: implement cast checking.
      return value
    },

    'uuid': function() {
        var buf = new Uint16Array(8);
        crypto.getRandomValues(buf);
        var S4 = function(num) {
            var ret = num.toString(16);
            while(ret.length < 4){
                ret = "0"+ret;
            }
            return ret;
        };
        return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    },

    'nativenew': function(type) {
      return function () {
        var newInstance = Object.create(type.prototype);
        newInstance = type.apply(newInstance, arguments) || newInstance;
        return newInstance;
      };
    },

    'nominalroot': function(instance) {
      if (instance.$wrapped) {
        return instance.$wrapped;
      }

      return instance;
    },

    'nominalwrap': function(instance, type) {
      return type.new($t.nominalroot(instance))
    },

    'nominalunwrap': function(instance) {
      return instance.$wrapped;
    },

    'workerwrap': function(methodId, f) {
      $w[methodId] = f;

      // If already inside a worker, return a function to execute asynchronously locally.
      if (!$__currentScriptSrc) {
        return function() {
          var promise = new Promise(function(resolve, reject) {
            $global.setTimeout(function() {
              f().then(function(value) {
                resolve(value);
              }).catch(function(value) {
                reject(value);
              });
            }, 0);
          });
          return promise;
        };
      }

      // Otherwise return a function to execute via a worker.
      return function() {
         var args = Array.prototype.slice.call(arguments);
         var token = $t.uuid();

         var promise = new Promise(function(resolve, reject) {
           var worker = new Worker($__currentScriptSrc + "?__serulian_async_token=" + token);
           worker.onmessage = function(e) {
              if (!e.isTrusted) {
                worker.terminate();
                return;
              }

              var data = e.data;
              if (data['token'] != token) {
                return;
              }

              if (data['result']) {
                resolve(data['result']);
              } else {
                reject(data['reject']);
              }

              worker.terminate();
           };

           worker.postMessage({
            'action': 'invoke',
            'arguments': args,
            'method': methodId,
            'token': token
           });
         });
         return promise;
      };
    },

    'property': function(getter, opt_setter) {
      var f = function() {
        if (arguments.length == 1) {
          return opt_setter.apply(this, arguments);
        } else {
          return getter.apply(this, arguments);
        }
      };

      f.$property = true;
      return f;
    },

    'dynamicaccess': function(obj, name) {
      if (obj == null || obj[name] == null) {
        return null;
      }

      var value = obj[name];
      if (typeof value == 'function' && value.$property) {
        return $promise.wrap(function() {
          return value.apply(obj, arguments);
        });
      }

      return value
    },

    'nullcompare': function(first, second) {
      return first == null ? second : first;
    },

  	'sm': function(caller) {
  		return {
        resources: {},
  			current: 0,
  			next: caller,

        pushr: function(value, name) {
          this.resources[name] = value;
        },

        popr: function(names) {
          var promises = [];

          for (var i = 0; i < arguments.length; ++i) {
            var name = arguments[i];
            if (this.resources[name]) {
              promises.push(this.resources[name].Release());
              delete this.resources[name];
            }
          }

          if (promises.length > 0) {
            return $promise.all(promises);
          } else {
            return $promise.resolve(null);
          }
        },

        popall: function() {
          for (var name in this.resources) {
            if (this.resources.hasOwnProperty(name)) {
              this.resources[name].Release();
            }
          }
        }
  		};
  	}
  };

  var $promise = {
  	'build': function(statemachine) {
  		return new Promise(function(resolve, reject) {
        statemachine.resolve = function(value) {
          statemachine.popall();
          statemachine.current = -1;
          resolve(value);
        };

        statemachine.reject = function(value) {
          statemachine.popall();
          statemachine.current = -1;
          reject(value);
        };

  			var continueFunc = function() {
  				if (statemachine.current < 0) {
  					return;
  				}

  				statemachine.next(callFunc);
			  };

        var callFunc = function() {
    			continueFunc();
          if (statemachine.current < 0) {
            statemachine.resolve(null);
          }
        };

        callFunc();
  		});
  	},

  	'all': function(promises) {
  		return Promise.all(promises);
  	},

  	'empty': function() {
  		return new Promise(function() {
  			resolve();
  		});
  	},

    'resolve': function(value) {
      return Promise.resolve(value);
    },

  	'wrap': function(func) {
  		return Promise.resolve(func());
  	},

    'translate': function(prom) {
       if (!prom.Then) {
         return prom;
       }

       return {
          'then': function() {
             return prom.Then.apply(prom, arguments);
          },
          'catch': function() {
             return prom.Catch.apply(prom, arguments);
          }
       };
    }
  };

  var moduleInits = [];

  var $module = function(name, creator) {
  	var module = {};

    var parts = name.split('.');
    var current = $g;
    for (var i = 0; i < parts.length - 1; ++i) {
      if (!current[parts[i]]) {
        current[parts[i]] = {};
      }
      current = current[parts[i]]
    }

    current[parts[parts.length - 1]] = module;

  	module.$init = function(cpromise) {
  	  moduleInits.push(cpromise);
  	};

    module.$newtypebuilder = function(kind) {
      return function(name, hasGenerics, alias, creator) {
        var buildType = function(n, args) {
          var tpe = new Function("return function " + n + "() {};")();
          creator.apply(tpe, args || []);

          if (kind == 'type') {
            tpe.prototype.toJSON = function() {
              return $t.nominalunwrap(this);
            };
          } else if (kind == 'struct') {
            // Stringify.
            tpe.prototype.Stringify = function(T) {
              var $this = this;
              return function() {
                // Special case JSON, as it uses an internal method.
                if (T == $a['$json']) {
                  return $promise.resolve(JSON.stringify($this.data));
                }

                return T.Get().then(function(resolved) {
                  return resolved.Stringify($t.any)($this.data);
                });
              };
            };

            // Parse.
            tpe.Parse = function(T) {
              return function(value) {
                // TODO: Validate the struct.

                // Special case JSON for performance, as it uses an internal method.
                if (T == $a['$json']) {
                  var created = new tpe();
                  created.data = JSON.parse($t.nominalunwrap(value));
                  return $promise.resolve(created);
                }

                return T.Get().then(function(resolved) {
                  return (resolved.Parse($t.any)(value)).then(function(parsed) {
                    var created = new tpe();
                    // TODO: *efficiently* unwrap internal nominal types.
                    created.data = JSON.parse(JSON.stringify($t.nominalunwrap(parsed)));
                    return $promise.resolve(created);
                  });
                });
              };
            };
          }

          return tpe;
        };

        if (hasGenerics) {
          module[name] = function(__genericargs) {
            var fullName = name;
            for (var i = 0; i < arguments.length; ++i) {
              fullName = fullName + '_' + arguments[i].name;
            }

            return buildType(fullName, arguments);
          };
        } else {
          module[name] = buildType(name);
        }

        if (alias) {
          $a[alias] = module[name];
        }
      };
    };

    module.$struct = module.$newtypebuilder('struct');
  	module.$class = module.$newtypebuilder('class');
  	module.$interface = module.$newtypebuilder('interface');
    module.$type = module.$newtypebuilder('type');

  	creator.call(module)
  };

  {{ range $idx, $kv := .Iter }}
  	{{ $kv.Value }}
  {{ end }}

  $g.executeWorkerMethod = function(token) {
    $global.onmessage = function(e) {
      if (!e.isTrusted) {
        $global.close();
        return;
      }

      var data = e.data;
      if (data['token'] != token) {
        throw Error('Invalid token')
        $global.close();
      }

      switch (data['action']) {
        case 'invoke':
          var methodId = data['method'];
          var arguments = data['arguments'];
          var method = $w[methodId];

          method.apply(null, arguments).then(function(result) {
            $global.postMessage({
              'result': result,
              'token': token
            });
            $global.close();
          }).catch(function(reject) {
            try {
              $global.postMessage({
                'reject': reject,
                'token': token
              });
            } catch (e) {
              throw reject;
            }

            $global.close();
          });
          break
      }
    };
  };

  return $promise.all(moduleInits).then(function() {
  	return $g;
  });
})(this)

// Handle web-worker calls.
if (typeof importScripts === 'function') {
  var runWorker = function() {
    var search = location.search;
    if (!search || search[0] != '?') {
      return;
    }

    var searchPairs = search.substr(1).split('&')
    if (searchPairs.length < 1) {
      return;
    }

    for (var i = 0; i < searchPairs.length; ++i) {
      var pair = searchPairs[i].split('=');
      if (pair[0] == '__serulian_async_token') {
        this.Serulian.then(function(global) {
          global.executeWorkerMethod(pair[1]);
        });
        return;
      }
    }

    close();
  };
  runWorker();
}
`
<|endoftext|>


<commit_before>// Code generated by go-swagger; DO NOT EDIT.

package restapi

import (
	"crypto/tls"
	"net/http"

	log "github.com/sirupsen/logrus"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

	errors "github.com/go-openapi/errors"
	runtime "github.com/go-openapi/runtime"
	"github.com/go-openapi/swag"
	graceful "github.com/tylerb/graceful"

	"github.com/solo-io/squash/pkg/platforms"
	"github.com/solo-io/squash/pkg/platforms/debug"
	"github.com/solo-io/squash/pkg/platforms/kubernetes"
	"github.com/solo-io/squash/pkg/restapi/operations"
	"github.com/solo-io/squash/pkg/restapi/operations/debugattachment"
	"github.com/solo-io/squash/pkg/restapi/operations/debugrequest"
	"github.com/solo-io/squash/pkg/server"
)

// This file is safe to edit. Once it exists it will not be overwritten

//go:generate swagger generate server --target ../pkg --name Squash --spec ../api.yaml --exclude-main

var (
	options = &struct {
		Cluster    string `long:"cluster" short:"c" description:"Cluster type. currently only kube"`
		KubeConfig string `long:"kubeconfug" description:"Path to kube config file to use to connect to the cluster. in cluster is used if not provided"`
		KubeUrl    string `long:"kubeurl" description:"Kube url (useful with kubectl proxy)"`
	}{"kube", "", ""}
)

func configureFlags(api *operations.SquashAPI) {

	api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{
		swag.CommandLineOptionsGroup{
			LongDescription:  "cluster related operations",
			ShortDescription: "cluster",
			Options:          options,
		},
	}
}

func configureAPI(api *operations.SquashAPI) http.Handler {
	log.SetLevel(log.DebugLevel)
	// configure the api here
	api.ServeError = errors.ServeError

	// Set your custom logger if needed. Default one is log.Printf
	// Expected interface func(string, ...interface{})
	//
	// Example:
	// api.Logger = log.Printf

	api.JSONConsumer = runtime.JSONConsumer()

	api.JSONProducer = runtime.JSONProducer()

	var cl platforms.ContainerLocator = nil

	data := server.NewServerData()
	dataStore := server.NewNOPDataStore()

	switch options.Cluster {
	case "kube":
		var config *rest.Config = nil
		if options.KubeConfig != "" {
			var err error
			config, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
				&clientcmd.ClientConfigLoadingRules{ExplicitPath: options.KubeConfig},
				&clientcmd.ConfigOverrides{
					ClusterInfo: clientcmdapi.Cluster{
						Server: options.KubeUrl,
					},
				}).ClientConfig()

			if err != nil {
				log.Fatalln(err)
			}
		} else if options.KubeUrl != "" {
			config = &rest.Config{Host: options.KubeUrl}
		}

		kube, err := kubernetes.NewKubeOperations(nil, config)
		if err != nil {
			log.Fatalln(err)
		}
		cl = kube
		dataStore, err = kubernetes.NewCRDDataStore(config, data)
		if err != nil {
			log.Fatalln(err)
		}
	case "debug":
		var d debug.DebugPlatform
		cl = &d
	default:
		panic("Invalid cluster option. perhaps you meant 'debug'?")
	}

	handler := server.NewRestHandler(data, cl, dataStore)

	api.DebugattachmentAddDebugAttachmentHandler = debugattachment.AddDebugAttachmentHandlerFunc(handler.DebugattachmentAddDebugAttachmentHandler)
	api.DebugrequestCreateDebugRequestHandler = debugrequest.CreateDebugRequestHandlerFunc(handler.DebugrequestCreateDebugRequestHandler)
	api.DebugattachmentDeleteDebugAttachmentHandler = debugattachment.DeleteDebugAttachmentHandlerFunc(handler.DebugattachmentDeleteDebugAttachmentHandler)
	api.DebugrequestDeleteDebugRequestHandler = debugrequest.DeleteDebugRequestHandlerFunc(handler.DebugrequestDeleteDebugRequestHandler)
	api.DebugattachmentGetDebugAttachmentHandler = debugattachment.GetDebugAttachmentHandlerFunc(handler.DebugattachmentGetDebugAttachmentHandler)
	api.DebugattachmentGetDebugAttachmentsHandler = debugattachment.GetDebugAttachmentsHandlerFunc(handler.DebugattachmentGetDebugAttachmentsHandler)
	api.DebugrequestGetDebugRequestsHandler = debugrequest.GetDebugRequestsHandlerFunc(handler.DebugrequestGetDebugRequestsHandler)
	api.DebugrequestGetDebugRequestHandler = debugrequest.GetDebugRequestHandlerFunc(handler.DebugrequestGetDebugRequestHandler)
	api.DebugattachmentPatchDebugAttachmentHandler = debugattachment.PatchDebugAttachmentHandlerFunc(handler.DebugattachmentPatchDebugAttachmentHandler)

	api.ServerShutdown = func() {}

	return setupGlobalMiddleware(api.Serve(setupMiddlewares))
}

// The TLS configuration before HTTPS server starts.
func configureTLS(tlsConfig *tls.Config) {
	// Make all necessary changes to the TLS configuration here.
}

// As soon as server is initialized but not run yet, this function will be called.
// If you need to modify a config, store server instance to stop it individually later, this is the place.
// This function can be called multiple times, depending on the number of serving schemes.
// scheme value will be set accordingly: "http", "https" or "unix"
func configureServer(s *graceful.Server, scheme, addr string) {
}

// The middleware configuration is for the handler executors. These do not apply to the swagger.json document.
// The middleware executes after routing but before authentication, binding and validation
func setupMiddlewares(handler http.Handler) http.Handler {
	return handler
}

// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
// So this is a good place to plug in a panic handling middleware, logging and metrics
func setupGlobalMiddleware(handler http.Handler) http.Handler {
	return handler
}
<commit_msg>comment out crds for now<commit_after>// Code generated by go-swagger; DO NOT EDIT.

package restapi

import (
	"crypto/tls"
	"net/http"

	log "github.com/sirupsen/logrus"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

	errors "github.com/go-openapi/errors"
	runtime "github.com/go-openapi/runtime"
	"github.com/go-openapi/swag"
	graceful "github.com/tylerb/graceful"

	"github.com/solo-io/squash/pkg/platforms"
	"github.com/solo-io/squash/pkg/platforms/debug"
	"github.com/solo-io/squash/pkg/platforms/kubernetes"
	"github.com/solo-io/squash/pkg/restapi/operations"
	"github.com/solo-io/squash/pkg/restapi/operations/debugattachment"
	"github.com/solo-io/squash/pkg/restapi/operations/debugrequest"
	"github.com/solo-io/squash/pkg/server"
)

// This file is safe to edit. Once it exists it will not be overwritten

//go:generate swagger generate server --target ../pkg --name Squash --spec ../api.yaml --exclude-main

var (
	options = &struct {
		Cluster    string `long:"cluster" short:"c" description:"Cluster type. currently only kube"`
		KubeConfig string `long:"kubeconfug" description:"Path to kube config file to use to connect to the cluster. in cluster is used if not provided"`
		KubeUrl    string `long:"kubeurl" description:"Kube url (useful with kubectl proxy)"`
	}{"kube", "", ""}
)

func configureFlags(api *operations.SquashAPI) {

	api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{
		swag.CommandLineOptionsGroup{
			LongDescription:  "cluster related operations",
			ShortDescription: "cluster",
			Options:          options,
		},
	}
}

func configureAPI(api *operations.SquashAPI) http.Handler {
	log.SetLevel(log.DebugLevel)
	// configure the api here
	api.ServeError = errors.ServeError

	// Set your custom logger if needed. Default one is log.Printf
	// Expected interface func(string, ...interface{})
	//
	// Example:
	// api.Logger = log.Printf

	api.JSONConsumer = runtime.JSONConsumer()

	api.JSONProducer = runtime.JSONProducer()

	var cl platforms.ContainerLocator = nil

	data := server.NewServerData()
	dataStore := server.NewNOPDataStore()

	switch options.Cluster {
	case "kube":
		var config *rest.Config = nil
		if options.KubeConfig != "" {
			var err error
			config, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
				&clientcmd.ClientConfigLoadingRules{ExplicitPath: options.KubeConfig},
				&clientcmd.ConfigOverrides{
					ClusterInfo: clientcmdapi.Cluster{
						Server: options.KubeUrl,
					},
				}).ClientConfig()

			if err != nil {
				log.Fatalln(err)
			}
		} else if options.KubeUrl != "" {
			config = &rest.Config{Host: options.KubeUrl}
		}

		kube, err := kubernetes.NewKubeOperations(nil, config)
		if err != nil {
			log.Fatalln(err)
		}
		cl = kube
		/*
			dataStore, err = kubernetes.NewCRDDataStore(config, data)
			if err != nil {
				log.Fatalln(err)
			}
		*/
	case "debug":
		var d debug.DebugPlatform
		cl = &d
	default:
		panic("Invalid cluster option. perhaps you meant 'debug'?")
	}

	handler := server.NewRestHandler(data, cl, dataStore)

	api.DebugattachmentAddDebugAttachmentHandler = debugattachment.AddDebugAttachmentHandlerFunc(handler.DebugattachmentAddDebugAttachmentHandler)
	api.DebugrequestCreateDebugRequestHandler = debugrequest.CreateDebugRequestHandlerFunc(handler.DebugrequestCreateDebugRequestHandler)
	api.DebugattachmentDeleteDebugAttachmentHandler = debugattachment.DeleteDebugAttachmentHandlerFunc(handler.DebugattachmentDeleteDebugAttachmentHandler)
	api.DebugrequestDeleteDebugRequestHandler = debugrequest.DeleteDebugRequestHandlerFunc(handler.DebugrequestDeleteDebugRequestHandler)
	api.DebugattachmentGetDebugAttachmentHandler = debugattachment.GetDebugAttachmentHandlerFunc(handler.DebugattachmentGetDebugAttachmentHandler)
	api.DebugattachmentGetDebugAttachmentsHandler = debugattachment.GetDebugAttachmentsHandlerFunc(handler.DebugattachmentGetDebugAttachmentsHandler)
	api.DebugrequestGetDebugRequestsHandler = debugrequest.GetDebugRequestsHandlerFunc(handler.DebugrequestGetDebugRequestsHandler)
	api.DebugrequestGetDebugRequestHandler = debugrequest.GetDebugRequestHandlerFunc(handler.DebugrequestGetDebugRequestHandler)
	api.DebugattachmentPatchDebugAttachmentHandler = debugattachment.PatchDebugAttachmentHandlerFunc(handler.DebugattachmentPatchDebugAttachmentHandler)

	api.ServerShutdown = func() {}

	return setupGlobalMiddleware(api.Serve(setupMiddlewares))
}

// The TLS configuration before HTTPS server starts.
func configureTLS(tlsConfig *tls.Config) {
	// Make all necessary changes to the TLS configuration here.
}

// As soon as server is initialized but not run yet, this function will be called.
// If you need to modify a config, store server instance to stop it individually later, this is the place.
// This function can be called multiple times, depending on the number of serving schemes.
// scheme value will be set accordingly: "http", "https" or "unix"
func configureServer(s *graceful.Server, scheme, addr string) {
}

// The middleware configuration is for the handler executors. These do not apply to the swagger.json document.
// The middleware executes after routing but before authentication, binding and validation
func setupMiddlewares(handler http.Handler) http.Handler {
	return handler
}

// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
// So this is a good place to plug in a panic handling middleware, logging and metrics
func setupGlobalMiddleware(handler http.Handler) http.Handler {
	return handler
}
<|endoftext|>


<commit_before>package gitmedia

import (
	core ".."
	"flag"
	"os"
	"os/exec"
	"path/filepath"
)

var commands = make(map[string]func(*Command) RunnableCommand)

func Run() {
	runcmd := true
	subname := SubCommand(1)

	if subname == "help" {
		runcmd = false
		subname = SubCommand(2)
	}

	cmd := NewCommand(filepath.Base(os.Args[0]), subname)
	cmdcb, ok := commands[subname]
	if ok {
		subcmd := cmdcb(cmd)
		subcmd.Setup()

		if runcmd {
			subcmd.Parse()
			subcmd.Run()
		} else {
			subcmd.Usage()
		}
	} else {
		missingCommand(cmd, subname)
	}
}

func SubCommand(pos int) string {
	if len(os.Args) < (pos + 1) {
		return "version"
	} else {
		return os.Args[pos]
	}
}

func NewCommand(name, subname string) *Command {
	var args []string
	if len(os.Args) > 1 {
		args = os.Args[2:]
	}

	return &Command{name, subname, flag.NewFlagSet(os.Args[0], flag.ExitOnError), args, args}
}

func PipeMediaCommand(name string, args ...string) error {
	return PipeCommand("bin/"+name, args...)
}

func PipeCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

type RunnableCommand interface {
	Setup()
	Parse()
	Run()
	Usage()
}

type Command struct {
	Name        string
	SubCommand  string
	FlagSet     *flag.FlagSet
	Args        []string
	SubCommands []string
}

func (c *Command) Usage() {
	core.Print("usage: %s %s", c.Name, c.SubCommand)
	c.FlagSet.PrintDefaults()
}

func (c *Command) Parse() {
	core.SetupDebugging(c.FlagSet)
	c.FlagSet.SetOutput(core.ErrorWriter)
	c.FlagSet.Parse(c.Args)
	c.SubCommands = c.FlagSet.Args()
}

func (c *Command) Setup() {}
func (c *Command) Run()   {}

func registerCommand(name string, cmdcb func(*Command) RunnableCommand) {
	commands[name] = cmdcb
}

func missingCommand(cmd *Command, subname string) {
	core.Error("%s: '%s' is not a %s command.  See %s help.",
		cmd.Name, subname, cmd.Name, cmd.Name)
}
<commit_msg>ララララー ラララー ララ<commit_after>package gitmedia

import (
	core ".."
	"flag"
	"os"
	"os/exec"
	"path/filepath"
)

var commands = make(map[string]func(*Command) RunnableCommand)

func Run() {
	runcmd := true
	subname := SubCommand(1)

	if subname == "help" {
		runcmd = false
		subname = SubCommand(2)
	}

	cmd := NewCommand(filepath.Base(os.Args[0]), subname)
	cmdcb, ok := commands[subname]
	if ok {
		subcmd := cmdcb(cmd)
		subcmd.Setup()

		if runcmd {
			subcmd.Parse()
			subcmd.Run()
		} else {
			subcmd.Usage()
		}
	} else {
		missingCommand(cmd, subname)
	}
}

func SubCommand(pos int) string {
	if len(os.Args) < (pos + 1) {
		return "version"
	} else {
		return os.Args[pos]
	}
}

func NewCommand(name, subname string) *Command {
	var args []string
	if len(os.Args) > 1 {
		args = os.Args[2:]
	}

	fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	core.SetupDebugging(fs)
	fs.SetOutput(core.ErrorWriter)

	return &Command{name, subname, fs, args, args}
}

func PipeMediaCommand(name string, args ...string) error {
	return PipeCommand("bin/"+name, args...)
}

func PipeCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

type RunnableCommand interface {
	Setup()
	Parse()
	Run()
	Usage()
}

type Command struct {
	Name        string
	SubCommand  string
	FlagSet     *flag.FlagSet
	Args        []string
	SubCommands []string
}

func (c *Command) Usage() {
	core.Print("usage: %s %s", c.Name, c.SubCommand)
	c.FlagSet.PrintDefaults()
}

func (c *Command) Parse() {
	c.FlagSet.Parse(c.Args)
	c.SubCommands = c.FlagSet.Args()
}

func (c *Command) Setup() {}
func (c *Command) Run()   {}

func registerCommand(name string, cmdcb func(*Command) RunnableCommand) {
	commands[name] = cmdcb
}

func missingCommand(cmd *Command, subname string) {
	core.Error("%s: '%s' is not a %s command.  See %s help.",
		cmd.Name, subname, cmd.Name, cmd.Name)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/mitchellh/cli"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
)

type DeleteCommand struct {
	Ui 				cli.Ui
	InstanceId 		string
	OlderThan 		string
	RequireAtLeast	int
	DryRun			bool
}

// descriptions for args
var deleteDscrInstanceId = "The EC2 instance from which the AMIs to be deleted were originally created."
var deleteOlderThan = "Delete AMIs older than the specified time; accepts formats like '30d' or '4h'."
var requireAtLeast = "Never delete AMIs such that fewer than this number of AMIs will remain. E.g. require at least 3 AMIs remain."
var deleteDscrDryRun = "Execute a simulated run. Lists AMIs to be deleted, but does not actually delete them."

func (c *DeleteCommand) Help() string {
	return `ec2-snapper create <args> [--help]

Create an AMI of the given EC2 instance.

Available args are:
--instance      	` + deleteDscrInstanceId + `
--older-than    	` + deleteOlderThan + `
--require-at-least  ` + requireAtLeast + `
--dry-run       	` + deleteDscrDryRun
}

func (c *DeleteCommand) Synopsis() string {
	return "Delete the specified AMIs"
}

func (c *DeleteCommand) Run(args []string) int {

	// Handle the command-line args
	cmdFlags := flag.NewFlagSet("delete", flag.ExitOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }

	cmdFlags.StringVar(&c.InstanceId, "instance", "", deleteDscrInstanceId)
	cmdFlags.StringVar(&c.OlderThan, "older-than", "", deleteOlderThan)
	cmdFlags.IntVar(&c.RequireAtLeast, "require-at-least", 0, requireAtLeast)
	cmdFlags.BoolVar(&c.DryRun, "dry-run", false, deleteDscrDryRun)

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	// Check for required command-line args
	if c.InstanceId == "" {
		c.Ui.Error("ERROR: The argument '--instance' is required.")
		return 1
	}

	if c.OlderThan == "" {
		c.Ui.Error("ERROR: The argument '--older-than' is required.")
		return 1
	}

	if c.RequireAtLeast < 0 {
		c.Ui.Error("ERROR: The argument '--require-at-least' must be a positive integer.")
		return 1
	}

	// Warn the user that this is a dry run
	if c.DryRun {
		c.Ui.Warn("WARNING: This is a dry run, and no actions will be taken, despite what any output may say!")
	}

	// Create an EC2 service object; AWS region is picked up from the "AWS_REGION" env var.
	svc := ec2.New(nil)

	// Get a list of the existing AMIs that were created for the given EC2 instance
	resp, err := svc.DescribeImages(&ec2.DescribeImagesInput{
		Filters: []*ec2.Filter{
			&ec2.Filter{
				Name: aws.String("tag:ec2-snapper-instance-id"),
				Values: []*string{&c.InstanceId},
			},
		},
	})
	if err != nil && strings.Contains(err.Error(), "NoCredentialProviders") {
		c.Ui.Error("ERROR: No AWS credentials were found.  Either set the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or run this program on an EC2 instance that has an IAM Role with the appropriate permissions.")
		return 1
	} else if err != nil {
		panic(err)
	}
	if len(resp.Images) == 0 {
		c.Ui.Error("No AMIs were found for EC2 instance \"" + c.InstanceId + "\"")
		return 0
	}

	// Check that at least the --require-at-least number of AMIs exists
	if len(resp.Images) <= c.RequireAtLeast {
		c.Ui.Info("NO ACTION TAKEN. There are currently " + strconv.Itoa(len(resp.Images)) + " AMIs, and --require-at-least=" + strconv.Itoa(c.RequireAtLeast) + " so no further action can be taken.")
		return 0
	}

	// Get the AWS Account ID of the current AWS account
	// We need this to do a more efficient lookup on the snapshot volumes
	awsAccountId := *resp.Images[0].OwnerID
	c.Ui.Output("==> Identified current AWS Account Id as " + awsAccountId)

	// Parse our date range
	match, _ := regexp.MatchString("^[0-9]*(h|d|m)$", c.OlderThan)
	if ! match {
		c.Ui.Error("The --older-than value of \"" + c.OlderThan + "\" is not formatted properly.  Use formats like 30d or 24h")
		return 0
	}

	var minutes float64
	var hours float64

	// We were given a time like "12h"
	if match, _ := regexp.MatchString("^[0-9]*(h)$", c.OlderThan); match {
		hours, _ = strconv.ParseFloat(c.OlderThan[0:len(c.OlderThan)-1], 64)
	}

	// We were given a time like "15d"
	if match, _ := regexp.MatchString("^[0-9]*(d)$", c.OlderThan); match {
		hours, _ = strconv.ParseFloat(c.OlderThan[0:len(c.OlderThan)-1], 64)
		hours *= 24
	}

	// We were given a time like "5m"
	if match, _ := regexp.MatchString("^[0-9]*(m)$", c.OlderThan); match {
		minutes, _ = strconv.ParseFloat(c.OlderThan[0:len(c.OlderThan)-1], 64)
		hours = minutes/60
	}

	// Now filter the AMIs to only include those within our date range
	var filteredAmis[]*ec2.Image
	for i := 0; i < len(resp.Images); i++ {
		now := time.Now()
		creationDate, err := time.Parse(time.RFC3339Nano, *resp.Images[i].CreationDate)
		if err != nil {
			panic(err)
		}

		duration := now.Sub(creationDate)

		if duration.Hours() > hours {
			filteredAmis = append(filteredAmis, resp.Images[i])
		}
	}
	c.Ui.Output("==> Found " + strconv.Itoa(len(filteredAmis)) + " total AMIs for deletion.")

	if len(filteredAmis) == 0 {
		c.Ui.Error("No AMIs to delete.")
		return 0
	}

	// Get a list of every single snapshot in our account
	// (I wasn't able to find a better way to filter these, but suggestions welcome!)
	respDscrSnapshots, err := svc.DescribeSnapshots(&ec2.DescribeSnapshotsInput{
		OwnerIDs: []*string{&awsAccountId},
	})
	if err != nil {
		panic(err)
	}
	c.Ui.Output("==> Found " + strconv.Itoa(len(respDscrSnapshots.Snapshots)) + " total snapshots in this account.")

	// Begin deleting AMIs...
	for i := 0; i < len(filteredAmis); i++ {
		// Step 1: De-register the AMI
		c.Ui.Output(*filteredAmis[i].ImageID + ": De-registering AMI named \"" + *filteredAmis[i].Name + "\"...")
		_, err := svc.DeregisterImage(&ec2.DeregisterImageInput{
			DryRun: &c.DryRun,
			ImageID: filteredAmis[i].ImageID,
		})
		if err != nil {
			if ! strings.Contains(err.Error(), "DryRunOperation") {
				panic(err)
			}
		}

		// Step 2: Delete the corresponding AMI snapshot
		// Look at the "description" for each Snapshot to see if it contains our AMI id
		snapshotId := ""
		for j := 0; j < len(respDscrSnapshots.Snapshots); j++ {
			if strings.Contains(*respDscrSnapshots.Snapshots[j].Description, *filteredAmis[i].ImageID) {
				snapshotId = *respDscrSnapshots.Snapshots[j].SnapshotID
				break
			}
		}

		c.Ui.Output(*filteredAmis[i].ImageID + ": Deleting snapshot " + snapshotId + "...")
		svc.DeleteSnapshot(&ec2.DeleteSnapshotInput{
			DryRun: &c.DryRun,
			SnapshotID: &snapshotId,
		})

		c.Ui.Output(*filteredAmis[i].ImageID + ": Done!")
		c.Ui.Output("")
	}

	if c.DryRun {
		c.Ui.Info("==> DRY RUN. Had this not been a dry run, " + strconv.Itoa(len(filteredAmis)) + " AMI's and their corresponding snapshots would have been deleted.")
	} else {
		c.Ui.Info("==> Success! Deleted " + strconv.Itoa(len(filteredAmis)) + " AMI's and their corresponding snapshots.")
	}
	return 0
}

<commit_msg>Implemented requireAtLeast feature<commit_after>package main

import (
	"flag"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/mitchellh/cli"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	"math"
)

type DeleteCommand struct {
	Ui 				cli.Ui
	InstanceId 		string
	OlderThan 		string
	RequireAtLeast	int
	DryRun			bool
}

// descriptions for args
var deleteDscrInstanceId = "The EC2 instance from which the AMIs to be deleted were originally created."
var deleteOlderThan = "Delete AMIs older than the specified time; accepts formats like '30d' or '4h'."
var requireAtLeast = "Never delete AMIs such that fewer than this number of AMIs will remain. E.g. require at least 3 AMIs remain."
var deleteDscrDryRun = "Execute a simulated run. Lists AMIs to be deleted, but does not actually delete them."

func (c *DeleteCommand) Help() string {
	return `ec2-snapper create <args> [--help]

Create an AMI of the given EC2 instance.

Available args are:
--instance      	` + deleteDscrInstanceId + `
--older-than    	` + deleteOlderThan + `
--require-at-least  ` + requireAtLeast + `
--dry-run       	` + deleteDscrDryRun
}

func (c *DeleteCommand) Synopsis() string {
	return "Delete the specified AMIs"
}

func (c *DeleteCommand) Run(args []string) int {

	// Handle the command-line args
	cmdFlags := flag.NewFlagSet("delete", flag.ExitOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }

	cmdFlags.StringVar(&c.InstanceId, "instance", "", deleteDscrInstanceId)
	cmdFlags.StringVar(&c.OlderThan, "older-than", "", deleteOlderThan)
	cmdFlags.IntVar(&c.RequireAtLeast, "require-at-least", 0, requireAtLeast)
	cmdFlags.BoolVar(&c.DryRun, "dry-run", false, deleteDscrDryRun)

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	// Check for required command-line args
	if c.InstanceId == "" {
		c.Ui.Error("ERROR: The argument '--instance' is required.")
		return 1
	}

	if c.OlderThan == "" {
		c.Ui.Error("ERROR: The argument '--older-than' is required.")
		return 1
	}

	if c.RequireAtLeast < 0 {
		c.Ui.Error("ERROR: The argument '--require-at-least' must be a positive integer.")
		return 1
	}

	// Warn the user that this is a dry run
	if c.DryRun {
		c.Ui.Warn("WARNING: This is a dry run, and no actions will be taken, despite what any output may say!")
	}

	// Create an EC2 service object; AWS region is picked up from the "AWS_REGION" env var.
	svc := ec2.New(nil)

	// Get a list of the existing AMIs that were created for the given EC2 instance
	resp, err := svc.DescribeImages(&ec2.DescribeImagesInput{
		Filters: []*ec2.Filter{
			&ec2.Filter{
				Name: aws.String("tag:ec2-snapper-instance-id"),
				Values: []*string{&c.InstanceId},
			},
		},
	})
	if err != nil && strings.Contains(err.Error(), "NoCredentialProviders") {
		c.Ui.Error("ERROR: No AWS credentials were found.  Either set the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or run this program on an EC2 instance that has an IAM Role with the appropriate permissions.")
		return 1
	} else if err != nil {
		panic(err)
	}
	if len(resp.Images) == 0 {
		c.Ui.Error("No AMIs were found for EC2 instance \"" + c.InstanceId + "\"")
		return 0
	}

	// Check that at least the --require-at-least number of AMIs exists
	// - Note that even if this passes, we still want to avoid deleting so many AMIs that we go below the threshold
	if len(resp.Images) <= c.RequireAtLeast {
		c.Ui.Info("NO ACTION TAKEN. There are currently " + strconv.Itoa(len(resp.Images)) + " AMIs, and --require-at-least=" + strconv.Itoa(c.RequireAtLeast) + " so no further action can be taken.")
		return 0
	}

	// Get the AWS Account ID of the current AWS account
	// We need this to do a more efficient lookup on the snapshot volumes
	awsAccountId := *resp.Images[0].OwnerID
	c.Ui.Output("==> Identified current AWS Account Id as " + awsAccountId)

	// Parse our date range
	match, _ := regexp.MatchString("^[0-9]*(h|d|m)$", c.OlderThan)
	if ! match {
		c.Ui.Error("The --older-than value of \"" + c.OlderThan + "\" is not formatted properly.  Use formats like 30d or 24h")
		return 0
	}

	var minutes float64
	var hours float64

	// We were given a time like "12h"
	if match, _ := regexp.MatchString("^[0-9]*(h)$", c.OlderThan); match {
		hours, _ = strconv.ParseFloat(c.OlderThan[0:len(c.OlderThan)-1], 64)
	}

	// We were given a time like "15d"
	if match, _ := regexp.MatchString("^[0-9]*(d)$", c.OlderThan); match {
		hours, _ = strconv.ParseFloat(c.OlderThan[0:len(c.OlderThan)-1], 64)
		hours *= 24
	}

	// We were given a time like "5m"
	if match, _ := regexp.MatchString("^[0-9]*(m)$", c.OlderThan); match {
		minutes, _ = strconv.ParseFloat(c.OlderThan[0:len(c.OlderThan)-1], 64)
		hours = minutes/60
	}

	// Now filter the AMIs to only include those within our date range
	var filteredAmis[]*ec2.Image
	for i := 0; i < len(resp.Images); i++ {
		now := time.Now()
		creationDate, err := time.Parse(time.RFC3339Nano, *resp.Images[i].CreationDate)
		if err != nil {
			panic(err)
		}

		duration := now.Sub(creationDate)

		if duration.Hours() > hours {
			filteredAmis = append(filteredAmis, resp.Images[i])
		}
	}
	c.Ui.Output("==> Found " + strconv.Itoa(len(filteredAmis)) + " total AMIs for deletion.")

	if len(filteredAmis) == 0 {
		c.Ui.Error("No AMIs to delete.")
		return 0
	}

	// Get a list of every single snapshot in our account
	// (I wasn't able to find a better way to filter these, but suggestions welcome!)
	respDscrSnapshots, err := svc.DescribeSnapshots(&ec2.DescribeSnapshotsInput{
		OwnerIDs: []*string{&awsAccountId},
	})
	if err != nil {
		panic(err)
	}
	c.Ui.Output("==> Found " + strconv.Itoa(len(respDscrSnapshots.Snapshots)) + " total snapshots in this account.")

	// Compute whether we should delete fewer AMIs to adhere to our --require-at-least requirement
	var numTotalAmis = len(resp.Images)
	var numFilteredAmis = len(filteredAmis)
	var numAmisToRemainAfterDelete = numTotalAmis - numFilteredAmis
	var numAmisToRemoveFromFiltered = math.Max(0.0, float64(c.RequireAtLeast - numAmisToRemainAfterDelete))

	if numAmisToRemoveFromFiltered > 0.0 {
		c.Ui.Output("==> Only deleting " + strconv.Itoa(len(filteredAmis) - int(numAmisToRemoveFromFiltered)) + " total AMIs to honor '--require-at-least=" + strconv.Itoa(c.RequireAtLeast) + "'.")
	}

	// Begin deleting AMIs...
	for i := 0; i < len(filteredAmis) - int(numAmisToRemoveFromFiltered); i++ {
		// Step 1: De-register the AMI
		c.Ui.Output(*filteredAmis[i].ImageID + ": De-registering AMI named \"" + *filteredAmis[i].Name + "\"...")
		_, err := svc.DeregisterImage(&ec2.DeregisterImageInput{
			DryRun: &c.DryRun,
			ImageID: filteredAmis[i].ImageID,
		})
		if err != nil {
			if ! strings.Contains(err.Error(), "DryRunOperation") {
				panic(err)
			}
		}

		// Step 2: Delete the corresponding AMI snapshot
		// Look at the "description" for each Snapshot to see if it contains our AMI id
		snapshotId := ""
		for j := 0; j < len(respDscrSnapshots.Snapshots); j++ {
			if strings.Contains(*respDscrSnapshots.Snapshots[j].Description, *filteredAmis[i].ImageID) {
				snapshotId = *respDscrSnapshots.Snapshots[j].SnapshotID
				break
			}
		}

		c.Ui.Output(*filteredAmis[i].ImageID + ": Deleting snapshot " + snapshotId + "...")
		svc.DeleteSnapshot(&ec2.DeleteSnapshotInput{
			DryRun: &c.DryRun,
			SnapshotID: &snapshotId,
		})

		c.Ui.Output(*filteredAmis[i].ImageID + ": Done!")
		c.Ui.Output("")
	}

	if c.DryRun {
		c.Ui.Info("==> DRY RUN. Had this not been a dry run, " + strconv.Itoa(len(filteredAmis)) + " AMI's and their corresponding snapshots would have been deleted.")
	} else {
		c.Ui.Info("==> Success! Deleted " + strconv.Itoa(len(filteredAmis) - int(numAmisToRemoveFromFiltered)) + " AMI's and their corresponding snapshots.")
	}
	return 0
}

<|endoftext|>


<commit_before>// Copyright 2015-present Oursky Ltd.
//
// 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.

package preprocessor

import (
	"context"
	"net/http"

	"github.com/Sirupsen/logrus"

	"github.com/skygeario/skygear-server/pkg/server/authtoken"
	"github.com/skygeario/skygear-server/pkg/server/router"
	"github.com/skygeario/skygear-server/pkg/server/skyerr"
)

func checkRequestAccessKey(payload *router.Payload, clientKey string, masterKey string) skyerr.Error {
	apiKey := payload.APIKey()
	if masterKey != "" && apiKey == masterKey {
		payload.AccessKey = router.MasterAccessKey
	} else if clientKey != "" && apiKey == clientKey {
		payload.AccessKey = router.ClientAccessKey
	} else if apiKey == "" {
		payload.AccessKey = router.NoAccessKey
	} else {
		return skyerr.NewErrorf(skyerr.AccessKeyNotAccepted, "Cannot verify api key: `%v`", apiKey)
	}
	payload.Context = context.WithValue(payload.Context, router.AccessKeyTypeContextKey, payload.AccessKey)
	return nil
}

// AccessKeyValidationPreprocessor provides preprocess method to check the
// API key of the request.
type AccessKeyValidationPreprocessor struct {
	ClientKey string
	MasterKey string
	AppName   string
}

func (p AccessKeyValidationPreprocessor) Preprocess(payload *router.Payload, response *router.Response) int {
	if err := checkRequestAccessKey(payload, p.ClientKey, p.MasterKey); err != nil {
		response.Err = err
		return http.StatusUnauthorized
	}

	if payload.AccessKey == router.NoAccessKey {
		response.Err = skyerr.NewErrorf(skyerr.NotAuthenticated, "Api key is empty")
		return http.StatusUnauthorized
	}

	payload.AppName = p.AppName
	return http.StatusOK
}

// UserAuthenticator provides preprocess method to authenicate a user
// with access token or non-login user without api key.
type UserAuthenticator struct {
	ClientKey  string
	MasterKey  string
	AppName    string
	TokenStore authtoken.Store
}

func (p *UserAuthenticator) Preprocess(payload *router.Payload, response *router.Response) int {
	if err := checkRequestAccessKey(payload, p.ClientKey, p.MasterKey); err != nil {
		response.Err = err
		return http.StatusUnauthorized
	}

	// If payload contains an access token, check whether if the access
	// token is valid. API Key is not required if there is valid access token.
	if tokenString := payload.AccessTokenString(); tokenString != "" {
		store := p.TokenStore
		token := authtoken.Token{}

		if err := store.Get(tokenString, &token); err != nil {
			if _, ok := err.(*authtoken.NotFoundError); ok {
				log.WithFields(logrus.Fields{
					"token": tokenString,
					"err":   err,
				}).Infoln("Token not found")

				response.Err = skyerr.NewError(skyerr.AccessTokenNotAccepted, "token does not exist or it has expired")
			} else {
				response.Err = skyerr.MakeError(err)
			}
			return http.StatusUnauthorized
		}

		payload.AppName = token.AppName
		payload.UserInfoID = token.UserInfoID
		payload.Context = context.WithValue(payload.Context, router.UserIDContextKey, token.UserInfoID)
		payload.AccessToken = token
		return http.StatusOK
	}

	if payload.AccessKey == router.NoAccessKey {
		response.Err = skyerr.NewErrorf(skyerr.NotAuthenticated, "Both api key and access token are empty")
		return http.StatusUnauthorized
	}

	// For master access key, it is possible to impersonate any user of
	// the caller's choosing.
	if payload.HasMasterKey() {
		if userID, ok := payload.Data["_user_id"].(string); ok {
			payload.UserInfoID = userID
			payload.Context = context.WithValue(payload.Context, router.UserIDContextKey, userID)
		}
	}

	payload.AppName = p.AppName
	return http.StatusOK
}
<commit_msg>Workaround the design where access key is overwritten during auth<commit_after>// Copyright 2015-present Oursky Ltd.
//
// 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.

package preprocessor

import (
	"context"
	"net/http"

	"github.com/Sirupsen/logrus"

	"github.com/skygeario/skygear-server/pkg/server/authtoken"
	"github.com/skygeario/skygear-server/pkg/server/router"
	"github.com/skygeario/skygear-server/pkg/server/skyerr"
)

func checkRequestAccessKey(payload *router.Payload, clientKey string, masterKey string) skyerr.Error {
	if payload.AccessKey != router.NoAccessKey {
		return nil
	}
	apiKey := payload.APIKey()
	if masterKey != "" && apiKey == masterKey {
		payload.AccessKey = router.MasterAccessKey
	} else if clientKey != "" && apiKey == clientKey {
		payload.AccessKey = router.ClientAccessKey
	} else if apiKey == "" {
		payload.AccessKey = router.NoAccessKey
	} else {
		return skyerr.NewErrorf(skyerr.AccessKeyNotAccepted, "Cannot verify api key: `%v`", apiKey)
	}
	payload.Context = context.WithValue(payload.Context, router.AccessKeyTypeContextKey, payload.AccessKey)
	return nil
}

// AccessKeyValidationPreprocessor provides preprocess method to check the
// API key of the request.
type AccessKeyValidationPreprocessor struct {
	ClientKey string
	MasterKey string
	AppName   string
}

func (p AccessKeyValidationPreprocessor) Preprocess(payload *router.Payload, response *router.Response) int {
	if err := checkRequestAccessKey(payload, p.ClientKey, p.MasterKey); err != nil {
		response.Err = err
		return http.StatusUnauthorized
	}

	if payload.AccessKey == router.NoAccessKey {
		response.Err = skyerr.NewErrorf(skyerr.NotAuthenticated, "Api key is empty")
		return http.StatusUnauthorized
	}

	payload.AppName = p.AppName
	return http.StatusOK
}

// UserAuthenticator provides preprocess method to authenicate a user
// with access token or non-login user without api key.
type UserAuthenticator struct {
	ClientKey  string
	MasterKey  string
	AppName    string
	TokenStore authtoken.Store
}

func (p *UserAuthenticator) Preprocess(payload *router.Payload, response *router.Response) int {
	if err := checkRequestAccessKey(payload, p.ClientKey, p.MasterKey); err != nil {
		response.Err = err
		return http.StatusUnauthorized
	}

	// If payload contains an access token, check whether if the access
	// token is valid. API Key is not required if there is valid access token.
	if tokenString := payload.AccessTokenString(); tokenString != "" {
		store := p.TokenStore
		token := authtoken.Token{}

		if err := store.Get(tokenString, &token); err != nil {
			if _, ok := err.(*authtoken.NotFoundError); ok {
				log.WithFields(logrus.Fields{
					"token": tokenString,
					"err":   err,
				}).Infoln("Token not found")

				response.Err = skyerr.NewError(skyerr.AccessTokenNotAccepted, "token does not exist or it has expired")
			} else {
				response.Err = skyerr.MakeError(err)
			}
			return http.StatusUnauthorized
		}

		payload.AppName = token.AppName
		payload.UserInfoID = token.UserInfoID
		payload.Context = context.WithValue(payload.Context, router.UserIDContextKey, token.UserInfoID)
		payload.AccessToken = token
		return http.StatusOK
	}

	if payload.AccessKey == router.NoAccessKey {
		response.Err = skyerr.NewErrorf(skyerr.NotAuthenticated, "Both api key and access token are empty")
		return http.StatusUnauthorized
	}

	// For master access key, it is possible to impersonate any user of
	// the caller's choosing.
	if payload.HasMasterKey() {
		if userID, ok := payload.Data["_user_id"].(string); ok {
			payload.UserInfoID = userID
			payload.Context = context.WithValue(payload.Context, router.UserIDContextKey, userID)
		}
	}

	payload.AppName = p.AppName
	return http.StatusOK
}
<|endoftext|>


<commit_before>package beanspike

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"sync/atomic"

	as "github.com/aerospike/aerospike-client-go"
)

type Conn struct {
	aerospike    *as.Client
	clientID     string
	statsHandler func(string, string, float64)
}

func (conn *Conn) stats(event, tube string, count float64) {
	if conn.statsHandler != nil {
		conn.statsHandler(event, tube, count)
	}
}

type Tube struct {
	Conn  *Conn
	Name  string
	first bool
}

type Stats struct {
	Jobs        int
	Ready       int
	Buried      int
	Delayed     int
	Reserved    int
	Deleted     int
	JobSize     int
	UsedSize    int
	SkippedSize int
}

func DialDefault(statsHandler func(string, string, float64)) (*Conn, error) {
	host := AerospikeHost
	port := AerospikePort

	if h := os.Getenv(AerospikeHostEnv); h != "" {
		host = h
	}

	if p := os.Getenv(AerospikePortEnv); p != "" {
		var dh string
		var err error
		dh, port, err = parsePort(p)
		if err != nil {
			return nil, fmt.Errorf("invalid environment variable %v. %v", AerospikePortEnv, err)
		}

		if dh != "" {
			// Docker specified Host in the port env overrides AerospikeHostEnv
			host = dh
		}
	}

	return Dial("", host, port, statsHandler)
}

func Dial(id string, host string, port int, statsHandler func(string, string, float64)) (*Conn, error) {
	if id == "" {
		// generate a default Id
		id = genID()
	}
	client, err := as.NewClient(host, port)

	if err != nil {
		return nil, err
	}

	err = registerUDFs(client)
	if err != nil {
		return nil, err
	}

	return &Conn{
		aerospike:    client,
		clientID:     id,
		statsHandler: statsHandler,
	}, nil

}

var instanceCount int32

func genID() string {
	count := atomic.AddInt32(&instanceCount, 1)

	pid := os.Getpid()

	if host, err := os.Hostname(); err == nil {
		return fmt.Sprintf("%v:%v:%v", host, pid, count)
	}
	return fmt.Sprintf("????????:%v:%v", pid, count)
}

var portRE = regexp.MustCompile(`^tcp:\/\/(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b):(\d{1,5})$`)

// Parse port check is the port var is actually a Docker ENV
// as this can easily happen
func parsePort(portStr string) (host string, port int, err error) {
	match := portRE.FindAllStringSubmatch(portStr, -1)
	if match != nil {
		// Docker style port ENV
		host = match[0][1]
		portStr = match[0][2]
	}

	port, err = strconv.Atoi(portStr)
	return host, port, err
}
<commit_msg>debug galore<commit_after>package beanspike

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"sync/atomic"

	as "github.com/aerospike/aerospike-client-go"
)

type Conn struct {
	aerospike    *as.Client
	clientID     string
	statsHandler func(string, string, float64)
}

func (conn *Conn) stats(event, tube string, count float64) {
	if conn.statsHandler != nil {
		conn.statsHandler(event, tube, count)
	}
}

type Tube struct {
	Conn  *Conn
	Name  string
	first bool
}

type Stats struct {
	Jobs        int
	Ready       int
	Buried      int
	Delayed     int
	Reserved    int
	Deleted     int
	JobSize     int
	UsedSize    int
	SkippedSize int
}

func DialDefault(statsHandler func(string, string, float64)) (*Conn, error) {
	host := AerospikeHost
	port := AerospikePort

	if h := os.Getenv(AerospikeHostEnv); h != "" {
		host = h
	}

	if p := os.Getenv(AerospikePortEnv); p != "" {
		var dh string
		var err error
		dh, port, err = parsePort(p)
		if err != nil {
			return nil, fmt.Errorf("invalid environment variable %v. %v", AerospikePortEnv, err)
		}

		if dh != "" {
			// Docker specified Host in the port env overrides AerospikeHostEnv
			host = dh
		}
	}

	return Dial("", host, port, statsHandler)
}

func Dial(id string, host string, port int, statsHandler func(string, string, float64)) (*Conn, error) {
	fmt.Println("beanspike.Dial: host=", host)
	if id == "" {
		// generate a default Id
		id = genID()
	}
	client, err := as.NewClient(host, port)

	if err != nil {
		return nil, err
	}

	err = registerUDFs(client)
	if err != nil {
		return nil, err
	}

	return &Conn{
		aerospike:    client,
		clientID:     id,
		statsHandler: statsHandler,
	}, nil

}

var instanceCount int32

func genID() string {
	count := atomic.AddInt32(&instanceCount, 1)

	pid := os.Getpid()

	if host, err := os.Hostname(); err == nil {
		return fmt.Sprintf("%v:%v:%v", host, pid, count)
	}
	return fmt.Sprintf("????????:%v:%v", pid, count)
}

var portRE = regexp.MustCompile(`^tcp:\/\/(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b):(\d{1,5})$`)

// Parse port check is the port var is actually a Docker ENV
// as this can easily happen
func parsePort(portStr string) (host string, port int, err error) {
	match := portRE.FindAllStringSubmatch(portStr, -1)
	if match != nil {
		// Docker style port ENV
		host = match[0][1]
		portStr = match[0][2]
	}

	port, err = strconv.Atoi(portStr)
	return host, port, err
}
<|endoftext|>


<commit_before>package commands

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

// Populate man pages
//go:generate go run ../docs/man/mangen.go

var (
	Debugging    = false
	ErrorBuffer  = &bytes.Buffer{}
	ErrorWriter  = io.MultiWriter(os.Stderr, ErrorBuffer)
	OutputWriter = io.MultiWriter(os.Stdout, ErrorBuffer)
	RootCmd      = &cobra.Command{
		Use:   "git-lfs",
		Short: "Git LFS provides large file storage to Git.",
		Run: func(cmd *cobra.Command, args []string) {
			versionCommand(cmd, args)
			cmd.Usage()
		},
	}
	ManPages = make(map[string]string, 20)
)

// Error prints a formatted message to Stderr.  It also gets printed to the
// panic log if one is created for this command.
func Error(format string, args ...interface{}) {
	line := format
	if len(args) > 0 {
		line = fmt.Sprintf(format, args...)
	}
	fmt.Fprintln(ErrorWriter, line)
}

// Print prints a formatted message to Stdout.  It also gets printed to the
// panic log if one is created for this command.
func Print(format string, args ...interface{}) {
	line := fmt.Sprintf(format, args...)
	fmt.Fprintln(OutputWriter, line)
}

// Exit prints a formatted message and exits.
func Exit(format string, args ...interface{}) {
	Error(format, args...)
	os.Exit(2)
}

// Debug prints a formatted message if debugging is enabled.  The formatted
// message also shows up in the panic log, if created.
func Debug(format string, args ...interface{}) {
	if !Debugging {
		return
	}
	log.Printf(format, args...)
}

// LoggedError prints a formatted message to Stderr and writes a stack trace for
// the error to a log file without exiting.
func LoggedError(err error, format string, args ...interface{}) {
	Error(format, args...)
	file := handlePanic(err)

	if len(file) > 0 {
		fmt.Fprintf(os.Stderr, "\nErrors logged to %s\nUse `git lfs logs last` to view the log.\n", file)
	}
}

// Panic prints a formatted message, and writes a stack trace for the error to
// a log file before exiting.
func Panic(err error, format string, args ...interface{}) {
	LoggedError(err, format, args...)
	os.Exit(2)
}

func Run() {
	RootCmd.Execute()
}

func PipeMediaCommand(name string, args ...string) error {
	return PipeCommand("bin/"+name, args...)
}

func PipeCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func requireStdin(msg string) {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) != 0 {
		Error("Cannot read from STDIN. %s", msg)
		os.Exit(1)
	}
}

func requireInRepo() {
	if !lfs.InRepo() {
		Print("Not in a git repository.")
		os.Exit(128)
	}
}

func handlePanic(err error) string {
	if err == nil {
		return ""
	}

	return logPanic(err)
}

func logPanic(loggedError error) string {
	var fmtWriter io.Writer = os.Stderr

	now := time.Now()
	name := now.Format("20060102T150405.999999999")
	full := filepath.Join(lfs.LocalLogDir, name+".log")

	if err := os.MkdirAll(lfs.LocalLogDir, 0755); err != nil {
		full = ""
		fmt.Fprintf(fmtWriter, "Unable to log panic to %s: %s\n\n", lfs.LocalLogDir, err.Error())
	} else if file, err := os.Create(full); err != nil {
		filename := full
		full = ""
		defer func() {
			fmt.Fprintf(fmtWriter, "Unable to log panic to %s\n\n", filename)
			logPanicToWriter(fmtWriter, err)
		}()
	} else {
		fmtWriter = file
		defer file.Close()
	}

	logPanicToWriter(fmtWriter, loggedError)

	return full
}

func logPanicToWriter(w io.Writer, loggedError error) {
	// log the version
	gitV, err := git.Config.Version()
	if err != nil {
		gitV = "Error getting git version: " + err.Error()
	}

	fmt.Fprintln(w, lfs.UserAgent)
	fmt.Fprintln(w, gitV)

	// log the command that was run
	fmt.Fprintln(w)
	fmt.Fprintf(w, "$ %s", filepath.Base(os.Args[0]))
	if len(os.Args) > 0 {
		fmt.Fprintf(w, " %s", strings.Join(os.Args[1:], " "))
	}
	fmt.Fprintln(w)

	// log the error message and stack trace
	w.Write(ErrorBuffer.Bytes())
	fmt.Fprintln(w)

	fmt.Fprintln(w, loggedError.Error())

	if err, ok := loggedError.(ErrorWithStack); ok {
		fmt.Fprintln(w, err.InnerError())
		for key, value := range err.Context() {
			fmt.Fprintf(w, "%s=%s\n", key, value)
		}
		w.Write(err.Stack())
	} else {
		w.Write(lfs.Stack())
	}
	fmt.Fprintln(w, "\nENV:")

	// log the environment
	for _, env := range lfs.Environ() {
		fmt.Fprintln(w, env)
	}
}

type ErrorWithStack interface {
	Context() map[string]string
	InnerError() string
	Stack() []byte
}

// determineIncludeExcludePaths is a common function to take the string arguments
// for include/exclude and derive slices either from these options or from the
// common global config
func determineIncludeExcludePaths(includeArg, excludeArg string) (include, exclude []string) {
	var includePaths, excludePaths []string
	if len(includeArg) > 0 {
		for _, inc := range strings.Split(includeArg, ",") {
			inc = strings.TrimSpace(inc)
			includePaths = append(includePaths, inc)
		}
	} else {
		includePaths = lfs.Config.FetchIncludePaths()
	}
	if len(excludeArg) > 0 {
		for _, ex := range strings.Split(excludeArg, ",") {
			ex = strings.TrimSpace(ex)
			excludePaths = append(excludePaths, ex)
		}
	} else {
		excludePaths = lfs.Config.FetchExcludePaths()
	}
	return includePaths, excludePaths
}

func printHelp(commandName string) {
	if txt, ok := ManPages[commandName]; ok {
		fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(txt))
	} else {
		fmt.Fprintf(os.Stderr, "Sorry, no usage text found for %q\n", commandName)
	}
}

// help is used for 'git-lfs help <command>'
func help(cmd *cobra.Command, args []string) {
	if len(args) == 0 {
		printHelp("git-lfs")
	} else {
		printHelp(args[0])
	}

}

// usage is used for 'git-lfs <command> --help' or when invoked manually
func usage(cmd *cobra.Command) error {
	printHelp(cmd.Name())
	return nil
}

func init() {
	log.SetOutput(ErrorWriter)
	// Set up help/usage funcs based on manpage text
	RootCmd.SetHelpFunc(help)
	RootCmd.SetUsageFunc(usage)
}
<commit_msg>update help template so cmd.Short is not shown<commit_after>package commands

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/lfs"
	"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
)

// Populate man pages
//go:generate go run ../docs/man/mangen.go

var (
	Debugging    = false
	ErrorBuffer  = &bytes.Buffer{}
	ErrorWriter  = io.MultiWriter(os.Stderr, ErrorBuffer)
	OutputWriter = io.MultiWriter(os.Stdout, ErrorBuffer)
	RootCmd      = &cobra.Command{
		Use:   "git-lfs",
		Short: "Git LFS provides large file storage to Git.",
		Run: func(cmd *cobra.Command, args []string) {
			versionCommand(cmd, args)
			cmd.Usage()
		},
	}
	ManPages = make(map[string]string, 20)
)

// Error prints a formatted message to Stderr.  It also gets printed to the
// panic log if one is created for this command.
func Error(format string, args ...interface{}) {
	line := format
	if len(args) > 0 {
		line = fmt.Sprintf(format, args...)
	}
	fmt.Fprintln(ErrorWriter, line)
}

// Print prints a formatted message to Stdout.  It also gets printed to the
// panic log if one is created for this command.
func Print(format string, args ...interface{}) {
	line := fmt.Sprintf(format, args...)
	fmt.Fprintln(OutputWriter, line)
}

// Exit prints a formatted message and exits.
func Exit(format string, args ...interface{}) {
	Error(format, args...)
	os.Exit(2)
}

// Debug prints a formatted message if debugging is enabled.  The formatted
// message also shows up in the panic log, if created.
func Debug(format string, args ...interface{}) {
	if !Debugging {
		return
	}
	log.Printf(format, args...)
}

// LoggedError prints a formatted message to Stderr and writes a stack trace for
// the error to a log file without exiting.
func LoggedError(err error, format string, args ...interface{}) {
	Error(format, args...)
	file := handlePanic(err)

	if len(file) > 0 {
		fmt.Fprintf(os.Stderr, "\nErrors logged to %s\nUse `git lfs logs last` to view the log.\n", file)
	}
}

// Panic prints a formatted message, and writes a stack trace for the error to
// a log file before exiting.
func Panic(err error, format string, args ...interface{}) {
	LoggedError(err, format, args...)
	os.Exit(2)
}

func Run() {
	RootCmd.Execute()
}

func PipeMediaCommand(name string, args ...string) error {
	return PipeCommand("bin/"+name, args...)
}

func PipeCommand(name string, args ...string) error {
	cmd := exec.Command(name, args...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func requireStdin(msg string) {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) != 0 {
		Error("Cannot read from STDIN. %s", msg)
		os.Exit(1)
	}
}

func requireInRepo() {
	if !lfs.InRepo() {
		Print("Not in a git repository.")
		os.Exit(128)
	}
}

func handlePanic(err error) string {
	if err == nil {
		return ""
	}

	return logPanic(err)
}

func logPanic(loggedError error) string {
	var fmtWriter io.Writer = os.Stderr

	now := time.Now()
	name := now.Format("20060102T150405.999999999")
	full := filepath.Join(lfs.LocalLogDir, name+".log")

	if err := os.MkdirAll(lfs.LocalLogDir, 0755); err != nil {
		full = ""
		fmt.Fprintf(fmtWriter, "Unable to log panic to %s: %s\n\n", lfs.LocalLogDir, err.Error())
	} else if file, err := os.Create(full); err != nil {
		filename := full
		full = ""
		defer func() {
			fmt.Fprintf(fmtWriter, "Unable to log panic to %s\n\n", filename)
			logPanicToWriter(fmtWriter, err)
		}()
	} else {
		fmtWriter = file
		defer file.Close()
	}

	logPanicToWriter(fmtWriter, loggedError)

	return full
}

func logPanicToWriter(w io.Writer, loggedError error) {
	// log the version
	gitV, err := git.Config.Version()
	if err != nil {
		gitV = "Error getting git version: " + err.Error()
	}

	fmt.Fprintln(w, lfs.UserAgent)
	fmt.Fprintln(w, gitV)

	// log the command that was run
	fmt.Fprintln(w)
	fmt.Fprintf(w, "$ %s", filepath.Base(os.Args[0]))
	if len(os.Args) > 0 {
		fmt.Fprintf(w, " %s", strings.Join(os.Args[1:], " "))
	}
	fmt.Fprintln(w)

	// log the error message and stack trace
	w.Write(ErrorBuffer.Bytes())
	fmt.Fprintln(w)

	fmt.Fprintln(w, loggedError.Error())

	if err, ok := loggedError.(ErrorWithStack); ok {
		fmt.Fprintln(w, err.InnerError())
		for key, value := range err.Context() {
			fmt.Fprintf(w, "%s=%s\n", key, value)
		}
		w.Write(err.Stack())
	} else {
		w.Write(lfs.Stack())
	}
	fmt.Fprintln(w, "\nENV:")

	// log the environment
	for _, env := range lfs.Environ() {
		fmt.Fprintln(w, env)
	}
}

type ErrorWithStack interface {
	Context() map[string]string
	InnerError() string
	Stack() []byte
}

// determineIncludeExcludePaths is a common function to take the string arguments
// for include/exclude and derive slices either from these options or from the
// common global config
func determineIncludeExcludePaths(includeArg, excludeArg string) (include, exclude []string) {
	var includePaths, excludePaths []string
	if len(includeArg) > 0 {
		for _, inc := range strings.Split(includeArg, ",") {
			inc = strings.TrimSpace(inc)
			includePaths = append(includePaths, inc)
		}
	} else {
		includePaths = lfs.Config.FetchIncludePaths()
	}
	if len(excludeArg) > 0 {
		for _, ex := range strings.Split(excludeArg, ",") {
			ex = strings.TrimSpace(ex)
			excludePaths = append(excludePaths, ex)
		}
	} else {
		excludePaths = lfs.Config.FetchExcludePaths()
	}
	return includePaths, excludePaths
}

func printHelp(commandName string) {
	if txt, ok := ManPages[commandName]; ok {
		fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(txt))
	} else {
		fmt.Fprintf(os.Stderr, "Sorry, no usage text found for %q\n", commandName)
	}
}

// help is used for 'git-lfs help <command>'
func help(cmd *cobra.Command, args []string) {
	if len(args) == 0 {
		printHelp("git-lfs")
	} else {
		printHelp(args[0])
	}

}

// usage is used for 'git-lfs <command> --help' or when invoked manually
func usage(cmd *cobra.Command) error {
	printHelp(cmd.Name())
	return nil
}

func init() {
	log.SetOutput(ErrorWriter)
	// Set up help/usage funcs based on manpage text
	RootCmd.SetHelpFunc(help)
	RootCmd.SetHelpTemplate("{{.UsageString}}")
	RootCmd.SetUsageFunc(usage)
}
<|endoftext|>


<commit_before>package service

import (
	"database/sql"
	"errors"
	"fmt"

	"github.com/fritzpay/paymentd/pkg/config"
	"golang.org/x/net/context"
	"gopkg.in/inconshreveable/log15.v2"
)

// Context is a custom context which is used by the service pkg
type Context struct {
	context.Context

	cfg config.Config
	log log15.Logger

	apiKeychain *Keychain
	webKeychain *Keychain

	principalDBWrite    *sql.DB
	principalDBReadOnly *sql.DB

	paymentDBWrite    *sql.DB
	paymentDBReadOnly *sql.DB
}

// Value wraps the Context.Value
func (ctx *Context) Value(key interface{}) interface{} {
	switch key {
	case "cfg":
		return ctx.cfg
	case "log":
		return ctx.log
	case "keychain":
		return ctx.apiKeychain
	case "paymentDB":
		return ctx.paymentDBWrite
	case "principalDB":
		return ctx.principalDBWrite
	default:
		return ctx.Context.Value(key)
	}
}

// SetValue creates a new service context with the given value
func (ctx *Context) WithValue(key, value interface{}) *Context {
	return &Context{
		Context:             context.WithValue(ctx.Context, key, value),
		cfg:                 ctx.cfg,
		log:                 ctx.log,
		apiKeychain:         ctx.apiKeychain,
		webKeychain:         ctx.webKeychain,
		principalDBWrite:    ctx.principalDBWrite,
		principalDBReadOnly: ctx.principalDBReadOnly,
		paymentDBWrite:      ctx.paymentDBWrite,
		paymentDBReadOnly:   ctx.paymentDBReadOnly,
	}
}

// Config returns the config.Config associated with the context
func (ctx *Context) Config() *config.Config {
	return &ctx.cfg
}

// Log returns the log15.Logger associated with the context
func (ctx *Context) Log() log15.Logger {
	return ctx.log
}

// Keychain returns the authorization container keychain associated with the context
func (ctx *Context) APIKeychain() *Keychain {
	return ctx.apiKeychain
}

func (ctx *Context) WebKeychain() *Keychain {
	return ctx.webKeychain
}

type dbRequestReadOnly bool

// ReadOnly is a possible parameter for the ctx.xDB() methods. If this parameter
// is passed to the methods, they will attempt to return the read-only database connection
var ReadOnly = dbRequestReadOnly(true)

// PrincipalDB returns the *sql.DB for the principal DB
// If the parameter(s) contain a service.ReadOnly, the read-only connection will be returned if present
func (ctx *Context) PrincipalDB(ros ...dbRequestReadOnly) *sql.DB {
	var ro bool
	if len(ros) > 0 {
		for _, r := range ros {
			if r {
				ro = true
			}
		}
	}
	if !ro {
		return ctx.principalDBWrite
	}
	if ctx.principalDBReadOnly == nil {
		return ctx.principalDBWrite
	}
	return ctx.principalDBReadOnly
}

// SetPrincipalDB sets the principal DB connection(s)
// It will panic if the write connection is nil
func (ctx *Context) SetPrincipalDB(w, ro *sql.DB) {
	if w == nil {
		panic("write DB connection cannot be nil")
	}
	ctx.principalDBWrite, ctx.principalDBReadOnly = w, ro
}

// PaymentDB returns the *sql.DB for the payment DB
// If the parameter(s) contain a service.ReadOnly, the read-only connection will be returned if present
func (ctx *Context) PaymentDB(ros ...dbRequestReadOnly) *sql.DB {
	var ro bool
	if len(ros) > 0 {
		for _, r := range ros {
			if r {
				ro = true
			}
		}
	}
	if !ro {
		return ctx.paymentDBWrite
	}
	if ctx.paymentDBReadOnly == nil {
		return ctx.paymentDBWrite
	}
	return ctx.paymentDBReadOnly
}

// SetPaymentDB sets the payment DB connection(s)
// It will panic if the write connection is nil
func (ctx *Context) SetPaymentDB(w, ro *sql.DB) {
	if w == nil {
		panic("write DB connection cannot be nil")
	}
	ctx.paymentDBWrite, ctx.paymentDBReadOnly = w, ro
}

func (ctx *Context) registerKeychain(kc *Keychain, keys []string) error {
	var err error
	for _, k := range keys {
		err = kc.AddKey(k)
		if err != nil {
			return err
		}
	}
	return nil
}

func (ctx *Context) registerKeychainFromConfig() error {
	err := ctx.registerKeychain(ctx.apiKeychain, ctx.Config().API.AuthKeys)
	if err != nil {
		return err
	}
	err = ctx.registerKeychain(ctx.webKeychain, ctx.Config().Web.AuthKeys)
	if err != nil {
		return err
	}
	return nil
}

// NewContext creates a new service context for use in the service pkg
func NewContext(ctx context.Context, cfg config.Config, log log15.Logger) (*Context, error) {
	if log == nil {
		return nil, errors.New("log cannot be nil")
	}
	c := &Context{
		Context:     ctx,
		cfg:         cfg,
		log:         log,
		apiKeychain: NewKeychain(),
		webKeychain: NewKeychain(),
	}
	err := c.registerKeychainFromConfig()
	if err != nil {
		return nil, fmt.Errorf("error loading keys from config: %v", err)
	}
	return c, nil
}
<commit_msg>add rate limiter bound to service context<commit_after>package service

import (
	"database/sql"
	"errors"
	"fmt"
	"net/http"

	"github.com/fritzpay/paymentd/pkg/config"
	"golang.org/x/net/context"
	"gopkg.in/inconshreveable/log15.v2"
)

// Context is a custom context which is used by the service pkg
type Context struct {
	context.Context

	cfg config.Config
	log log15.Logger

	apiKeychain *Keychain
	webKeychain *Keychain

	principalDBWrite    *sql.DB
	principalDBReadOnly *sql.DB

	paymentDBWrite    *sql.DB
	paymentDBReadOnly *sql.DB

	rateLimit chan struct{}
}

// Value wraps the Context.Value
func (ctx *Context) Value(key interface{}) interface{} {
	switch key {
	case "cfg":
		return ctx.cfg
	case "log":
		return ctx.log
	case "keychain":
		return ctx.apiKeychain
	case "paymentDB":
		return ctx.paymentDBWrite
	case "principalDB":
		return ctx.principalDBWrite
	default:
		return ctx.Context.Value(key)
	}
}

// SetValue creates a new service context with the given value
func (ctx *Context) WithValue(key, value interface{}) *Context {
	return &Context{
		Context:             context.WithValue(ctx.Context, key, value),
		cfg:                 ctx.cfg,
		log:                 ctx.log,
		apiKeychain:         ctx.apiKeychain,
		webKeychain:         ctx.webKeychain,
		principalDBWrite:    ctx.principalDBWrite,
		principalDBReadOnly: ctx.principalDBReadOnly,
		paymentDBWrite:      ctx.paymentDBWrite,
		paymentDBReadOnly:   ctx.paymentDBReadOnly,
		rateLimit:           ctx.rateLimit,
	}
}

// Config returns the config.Config associated with the context
func (ctx *Context) Config() *config.Config {
	return &ctx.cfg
}

// Log returns the log15.Logger associated with the context
func (ctx *Context) Log() log15.Logger {
	return ctx.log
}

// Keychain returns the authorization container keychain associated with the context
func (ctx *Context) APIKeychain() *Keychain {
	return ctx.apiKeychain
}

func (ctx *Context) WebKeychain() *Keychain {
	return ctx.webKeychain
}

type dbRequestReadOnly bool

// ReadOnly is a possible parameter for the ctx.xDB() methods. If this parameter
// is passed to the methods, they will attempt to return the read-only database connection
var ReadOnly = dbRequestReadOnly(true)

// PrincipalDB returns the *sql.DB for the principal DB
// If the parameter(s) contain a service.ReadOnly, the read-only connection will be returned if present
func (ctx *Context) PrincipalDB(ros ...dbRequestReadOnly) *sql.DB {
	var ro bool
	if len(ros) > 0 {
		for _, r := range ros {
			if r {
				ro = true
			}
		}
	}
	if !ro {
		return ctx.principalDBWrite
	}
	if ctx.principalDBReadOnly == nil {
		return ctx.principalDBWrite
	}
	return ctx.principalDBReadOnly
}

// SetPrincipalDB sets the principal DB connection(s)
// It will panic if the write connection is nil
func (ctx *Context) SetPrincipalDB(w, ro *sql.DB) {
	if w == nil {
		panic("write DB connection cannot be nil")
	}
	ctx.principalDBWrite, ctx.principalDBReadOnly = w, ro
}

// PaymentDB returns the *sql.DB for the payment DB
// If the parameter(s) contain a service.ReadOnly, the read-only connection will be returned if present
func (ctx *Context) PaymentDB(ros ...dbRequestReadOnly) *sql.DB {
	var ro bool
	if len(ros) > 0 {
		for _, r := range ros {
			if r {
				ro = true
			}
		}
	}
	if !ro {
		return ctx.paymentDBWrite
	}
	if ctx.paymentDBReadOnly == nil {
		return ctx.paymentDBWrite
	}
	return ctx.paymentDBReadOnly
}

// SetPaymentDB sets the payment DB connection(s)
// It will panic if the write connection is nil
func (ctx *Context) SetPaymentDB(w, ro *sql.DB) {
	if w == nil {
		panic("write DB connection cannot be nil")
	}
	ctx.paymentDBWrite, ctx.paymentDBReadOnly = w, ro
}

func (ctx *Context) registerKeychain(kc *Keychain, keys []string) error {
	var err error
	for _, k := range keys {
		err = kc.AddKey(k)
		if err != nil {
			return err
		}
	}
	return nil
}

func (ctx *Context) registerKeychainFromConfig() error {
	err := ctx.registerKeychain(ctx.apiKeychain, ctx.Config().API.AuthKeys)
	if err != nil {
		return err
	}
	err = ctx.registerKeychain(ctx.webKeychain, ctx.Config().Web.AuthKeys)
	if err != nil {
		return err
	}
	return nil
}

func (ctx *Context) RateLimitHandler(parent http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		<-ctx.rateLimit
		parent.ServeHTTP(w, r)
		ctx.rateLimit <- struct{}{}
	})
}

// NewContext creates a new service context for use in the service pkg
func NewContext(ctx context.Context, cfg config.Config, log log15.Logger) (*Context, error) {
	if log == nil {
		return nil, errors.New("log cannot be nil")
	}
	c := &Context{
		Context:     ctx,
		cfg:         cfg,
		log:         log,
		apiKeychain: NewKeychain(),
		webKeychain: NewKeychain(),
	}
	err := c.registerKeychainFromConfig()
	if err != nil {
		return nil, fmt.Errorf("error loading keys from config: %v", err)
	}
	if cfg.Database.MaxOpenConns <= 0 {
		return nil, fmt.Errorf("invalid value for max open db conns %d", cfg.Database.MaxOpenConns)
	}
	c.rateLimit = make(chan struct{}, cfg.Database.MaxOpenConns)
	for i := 0; i < cfg.Database.MaxOpenConns; i++ {
		c.rateLimit <- struct{}{}
	}
	return c, nil
}
<|endoftext|>