Last active
August 29, 2015 14:04
-
-
Save cesarkawakami/c54b8707127de514e64a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
application: sample | |
version: one | |
runtime: go | |
api_version: go1 | |
skip_files: | |
- script.go | |
handlers: | |
- url: /_ah/remote_api | |
script: _go_app | |
login: admin | |
- url: /.* | |
script: _go_app |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package hello | |
import ( | |
_ "appengine/remote_api" | |
"fmt" | |
"net/http" | |
) | |
func init() { | |
http.HandleFunc("/", handler) | |
} | |
func handler(w http.ResponseWriter, r *http.Request) { | |
fmt.Fprint(w, "Hello, world!") | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ goapp deploy -application pndtest4 | |
01:07 AM Application: pndtest4 (was: sample); version: one | |
01:07 AM Host: appengine.google.com | |
01:07 AM | |
Starting update of app: pndtest4, version: one | |
01:07 AM Getting current resource limits. | |
Email: [email protected] | |
Password for [email protected]: | |
01:07 AM Scanning files on local disk. | |
01:07 AM Cloning 2 application files. | |
01:07 AM Uploading 2 files and blobs. | |
01:07 AM Uploaded 2 files and blobs | |
01:07 AM Compilation starting. | |
01:07 AM Compilation: 1 files left. | |
01:07 AM Compilation completed. | |
01:07 AM Starting deployment. | |
01:07 AM Checking if deployment succeeded. | |
01:07 AM Deployment successful. | |
01:07 AM Checking if updated app version is serving. | |
01:07 AM Completed update of app: pndtest4, version: one | |
$ goapp run ./script.go -host one-dot-pndtest4.appspot.com -email [email protected] -password_file [omitted] -kind_name SampleEntity delete | |
2014/08/06 01:08:15 appengine: not running under devappserver2; using some default configuration | |
2014/08/06 01:08:16 Successfully deleted 0 keys | |
$ goapp run ./script.go -host one-dot-pndtest4.appspot.com -email [email protected] -password_file [omitted] -kind_name SampleEntity add | |
2014/08/06 01:08:21 appengine: not running under devappserver2; using some default configuration | |
2014/08/06 01:08:25 Successfully created 40 entities | |
$ goapp run ./script.go -host one-dot-pndtest4.appspot.com -email [email protected] -password_file [omitted] -kind_name SampleEntity delete | |
2014/08/06 01:08:30 appengine: not running under devappserver2; using some default configuration | |
2014/08/06 01:08:30 Failed during query to get keys: API error 1 (datastore_v3: BAD_REQUEST): invalid handle: 4904724477798395918 | |
exit status 1 | |
$ goapp run ./script.go -host one-dot-pndtest4.appspot.com -email [email protected] -password_file [omitted] -kind_name SampleEntity delete_wi | |
th_limit | |
2014/08/06 01:08:37 appengine: not running under devappserver2; using some default configuration | |
2014/08/06 01:08:38 Successfully deleted 40 keys | |
$ goapp run ./script.go -host one-dot-pndtest4.appspot.com -email [email protected] -password_file [omitted] -kind_name SampleEntity delete | |
2014/08/06 01:08:44 appengine: not running under devappserver2; using some default configuration | |
2014/08/06 01:08:44 Successfully deleted 0 keys |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"appengine/datastore" | |
"appengine/remote_api" | |
"errors" | |
"flag" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"net/http/cookiejar" | |
"net/url" | |
"regexp" | |
"strings" | |
) | |
const NUM_ENTITIES_TO_INSERT = 40 | |
const QUERY_FETCH_LIMIT = 1000 | |
var ( | |
host = flag.String("host", "", "hostname of application") | |
email = flag.String("email", "", "email of an admin user for the application") | |
passwordFile = flag.String("password_file", "", "file which contains the user's password") | |
kindName = flag.String("kind_name", "", "name of the kind (an empty one) to be used") | |
) | |
func main() { | |
flag.Parse() | |
mode := flag.Arg(0) | |
if *host == "" || *email == "" || *passwordFile == "" || *kindName == "" || flag.Arg(0) == "" { | |
log.Fatalf("-host, -email, -passwordFile, -kindName and (add|delete|delete_with_limit) are required") | |
} | |
raw_password, err := ioutil.ReadFile(*passwordFile) | |
if err != nil { | |
log.Fatalf("Failed while reading password file %a: %v", *passwordFile, err) | |
} | |
password := strings.TrimSpace(string(raw_password)) | |
client := clientLoginClient(*host, *email, password) | |
context, err := remote_api.NewRemoteContext(*host, client) | |
if err != nil { | |
log.Fatalf("Failed to create context: %v", err) | |
} | |
switch mode { | |
case "delete": | |
keys, err := datastore.NewQuery(*kindName). | |
KeysOnly(). | |
GetAll(context, nil) | |
if err != nil { | |
log.Fatalf("Failed during query to get keys: %v", err) | |
} | |
if err := datastore.DeleteMulti(context, keys); err != nil { | |
log.Fatalf("Failed during key deletion: %v", err) | |
} | |
log.Printf("Successfully deleted %v keys", len(keys)) | |
case "delete_with_limit": | |
keys, err := datastore.NewQuery(*kindName). | |
Limit(QUERY_FETCH_LIMIT). | |
KeysOnly(). | |
GetAll(context, nil) | |
if err != nil { | |
log.Fatalf("Failed during query to get keys: %v", err) | |
} | |
if err := datastore.DeleteMulti(context, keys); err != nil { | |
log.Fatalf("Failed during key deletion: %v", err) | |
} | |
log.Printf("Successfully deleted %v keys", len(keys)) | |
case "add": | |
entities := make([]datastore.PropertyList, NUM_ENTITIES_TO_INSERT) | |
keys := make([]*datastore.Key, NUM_ENTITIES_TO_INSERT) | |
for i := 0; i < NUM_ENTITIES_TO_INSERT; i++ { | |
keys[i] = datastore.NewIncompleteKey(context, *kindName, nil) | |
} | |
keys, err := datastore.PutMulti(context, keys, entities) | |
if err != nil { | |
log.Fatalf("Failed while inserting entities: %v", err) | |
} | |
log.Printf("Successfully created %v entities", len(keys)) | |
} | |
} | |
// Blatantly copied from demos/remote_api/datastore_info.go | |
func clientLoginClient(host, email, password string) *http.Client { | |
jar, err := cookiejar.New(nil) | |
if err != nil { | |
log.Fatalf("failed to make cookie jar: %v", err) | |
} | |
client := &http.Client{ | |
Jar: jar, | |
} | |
v := url.Values{} | |
v.Set("Email", email) | |
v.Set("Passwd", password) | |
v.Set("service", "ah") | |
v.Set("source", "Misc-remote_api-0.1") | |
v.Set("accountType", "HOSTED_OR_GOOGLE") | |
resp, err := client.PostForm("https://www.google.com/accounts/ClientLogin", v) | |
if err != nil { | |
log.Fatalf("could not post login: %v", err) | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
if resp.StatusCode != http.StatusOK { | |
log.Fatalf("unsuccessful request: status %d; body %q", resp.StatusCode, body) | |
} | |
if err != nil { | |
log.Fatalf("unable to read response: %v", err) | |
} | |
m := regexp.MustCompile(`Auth=(\S+)`).FindSubmatch(body) | |
if m == nil { | |
log.Fatalf("no auth code in response %q", body) | |
} | |
auth := string(m[1]) | |
u := &url.URL{ | |
Scheme: "https", | |
Host: host, | |
Path: "/_ah/login", | |
RawQuery: "continue=/&auth=" + url.QueryEscape(auth), | |
} | |
// Disallow redirects. | |
redirectErr := errors.New("stopping redirect") | |
client.CheckRedirect = func(req *http.Request, via []*http.Request) error { | |
return redirectErr | |
} | |
resp, err = client.Get(u.String()) | |
if urlErr, ok := err.(*url.Error); !ok || urlErr.Err != redirectErr { | |
log.Fatalf("could not get auth cookies: %v", err) | |
} | |
defer resp.Body.Close() | |
body, err = ioutil.ReadAll(resp.Body) | |
if resp.StatusCode != http.StatusFound { | |
log.Fatalf("unsuccessful request: status %d; body %q", resp.StatusCode, body) | |
} | |
client.CheckRedirect = nil | |
return client | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment