func newFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (storage blobserver.Storage, err os.Error) { sto := &condStorage{ SimpleBlobHubPartitionMap: &blobserver.SimpleBlobHubPartitionMap{}, } receive := conf.OptionalStringOrObject("write") read := conf.RequiredString("read") remove := conf.OptionalString("remove", "") if err := conf.Validate(); err != nil { return nil, err } if receive != nil { sto.storageForReceive, err = buildStorageForReceive(ld, receive) if err != nil { return } } sto.read, err = ld.GetStorage(read) if err != nil { return } if remove != "" { sto.remove, err = ld.GetStorage(remove) if err != nil { return } } return sto, nil }
func newFromConfig(ld blobserver.Loader, config jsonconfig.Obj) (storage blobserver.Storage, err os.Error) { sto := &replicaStorage{ SimpleBlobHubPartitionMap: &blobserver.SimpleBlobHubPartitionMap{}, } sto.replicaPrefixes = config.RequiredList("backends") nReplicas := len(sto.replicaPrefixes) sto.minWritesForSuccess = config.OptionalInt("minWritesForSuccess", nReplicas) if err := config.Validate(); err != nil { return nil, err } if nReplicas == 0 { return nil, os.NewError("replica: need at least one replica") } if sto.minWritesForSuccess == 0 { sto.minWritesForSuccess = nReplicas } sto.replicas = make([]blobserver.Storage, nReplicas) for i, prefix := range sto.replicaPrefixes { replicaSto, err := ld.GetStorage(prefix) if err != nil { return nil, err } sto.replicas[i] = replicaSto } return sto, nil }
func newHandlerFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (http.Handler, os.Error) { indexPrefix := conf.RequiredString("index") // TODO: add optional help tips here? ownerBlobStr := conf.RequiredString("owner") if err := conf.Validate(); err != nil { return nil, err } indexHandler, err := ld.GetHandler(indexPrefix) if err != nil { return nil, fmt.Errorf("search config references unknown handler %q", indexPrefix) } indexer, ok := indexHandler.(Index) if !ok { return nil, fmt.Errorf("search config references invalid indexer %q (actually a %T)", indexPrefix, indexHandler) } ownerBlobRef := blobref.Parse(ownerBlobStr) if ownerBlobRef == nil { return nil, fmt.Errorf("search 'owner' has malformed blobref %q; expecting e.g. sha1-xxxxxxxxxxxx", ownerBlobStr) } return &Handler{ index: indexer, owner: ownerBlobRef, }, nil }
func newPublishFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) { ph := &PublishHandler{ bsLoader: ld, } ph.RootName = conf.RequiredString("rootName") ph.JSFiles = conf.OptionalList("js") ph.CSSFiles = conf.OptionalList("css") blobRoot := conf.RequiredString("blobRoot") searchRoot := conf.RequiredString("searchRoot") cachePrefix := conf.OptionalString("cache", "") bootstrapSignRoot := conf.OptionalString("devBootstrapPermanodeUsing", "") if err = conf.Validate(); err != nil { return } if ph.RootName == "" { return nil, os.NewError("invalid empty rootName") } bs, err := ld.GetStorage(blobRoot) if err != nil { return nil, fmt.Errorf("publish handler's blobRoot of %q error: %v", blobRoot, err) } ph.Storage = bs si, err := ld.GetHandler(searchRoot) if err != nil { return nil, fmt.Errorf("publish handler's searchRoot of %q error: %v", searchRoot, err) } var ok bool ph.Search, ok = si.(*search.Handler) if !ok { return nil, fmt.Errorf("publish handler's searchRoot of %q is of type %T, expecting a search handler", searchRoot, si) } if bootstrapSignRoot != "" { if t := ld.GetHandlerType(bootstrapSignRoot); t != "jsonsign" { return nil, fmt.Errorf("publish handler's devBootstrapPermanodeUsing must be of type jsonsign") } h, _ := ld.GetHandler(bootstrapSignRoot) jsonSign := h.(*JSONSignHandler) if err := ph.bootstrapPermanode(jsonSign); err != nil { return nil, fmt.Errorf("error bootstrapping permanode: %v", err) } } if cachePrefix != "" { bs, err := ld.GetStorage(cachePrefix) if err != nil { return nil, fmt.Errorf("publish handler's cache of %q error: %v", cachePrefix, err) } ph.Cache = bs } ph.staticHandler = http.FileServer(uiFiles) return ph, nil }
func newFromConfig(ld blobserver.Loader, config jsonconfig.Obj) (blobserver.Storage, os.Error) { blobPrefix := config.RequiredString("blobSource") indexer := &Indexer{ SimpleBlobHubPartitionMap: &blobserver.SimpleBlobHubPartitionMap{}, Host: config.OptionalString("host", "localhost"), User: config.RequiredString("user"), Password: config.OptionalString("password", ""), Database: config.RequiredString("database"), } if err := config.Validate(); err != nil { return nil, err } sto, err := ld.GetStorage(blobPrefix) if err != nil { return nil, err } indexer.BlobSource = sto // Good enough, for now: indexer.KeyFetcher = indexer.BlobSource //ownerBlobRef = client.SignerPublicKeyBlobref() //if ownerBlobRef == nil { // log.Fatalf("Public key not configured.") //} ok, err := indexer.IsAlive() if !ok { return nil, fmt.Errorf("Failed to connect to MySQL: %v", err) } version, err := indexer.SchemaVersion() if err != nil { return nil, fmt.Errorf("error getting schema version (need to init database?): %v", err) } if version != requiredSchemaVersion { if os.Getenv("CAMLI_ADVERTISED_PASSWORD") != "" { // Good signal that we're using the dev-server script, so help out // the user with a more useful tip: return nil, fmt.Errorf("database schema version is %d; expect %d (run \"./dev-server --wipe\" to wipe both your blobs and re-populate the database schema)", version, requiredSchemaVersion) } return nil, fmt.Errorf("database schema version is %d; expect %d (need to re-init/upgrade database?)", version, requiredSchemaVersion) } return indexer, nil }
func newJsonSignFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (http.Handler, os.Error) { pubKeyDestPrefix := conf.OptionalString("publicKeyDest", "") // either a short form ("26F5ABDA") or one the longer forms. keyId := conf.RequiredString("keyId") h := &JSONSignHandler{ secretRing: conf.OptionalString("secretRing", ""), } var err os.Error if err = conf.Validate(); err != nil { return nil, err } h.entity, err = jsonsign.EntityFromSecring(keyId, h.secretRingPath()) if err != nil { return nil, err } armoredPublicKey, err := jsonsign.ArmoredPublicKey(h.entity) ms := new(blobref.MemoryStore) h.pubKeyBlobRef, err = ms.AddBlob(crypto.SHA1, armoredPublicKey) if err != nil { return nil, err } h.pubKeyFetcher = ms if pubKeyDestPrefix != "" { sto, err := ld.GetStorage(pubKeyDestPrefix) if err != nil { return nil, err } h.pubKeyDest = sto go h.uploadPublicKey(armoredPublicKey) } h.pubKeyBlobRefServeSuffix = "camli/" + h.pubKeyBlobRef.String() h.pubKeyHandler = &handlers.GetHandler{ Fetcher: ms, AllowGlobalAccess: true, // just public keys } return h, nil }
func newSyncFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) { from := conf.RequiredString("from") to := conf.RequiredString("to") if err = conf.Validate(); err != nil { return } fromBs, err := ld.GetStorage(from) if err != nil { return } toBs, err := ld.GetStorage(to) if err != nil { return } synch, err := createSyncHandler(from, to, fromBs, toBs) if err != nil { return } return synch, nil }
func newFromConfig(ld blobserver.Loader, config jsonconfig.Obj) (storage blobserver.Storage, err os.Error) { sto := &shardStorage{ SimpleBlobHubPartitionMap: &blobserver.SimpleBlobHubPartitionMap{}, } sto.shardPrefixes = config.RequiredList("backends") if err := config.Validate(); err != nil { return nil, err } if len(sto.shardPrefixes) == 0 { return nil, os.NewError("shard: need at least one shard") } sto.shards = make([]blobserver.Storage, len(sto.shardPrefixes)) for i, prefix := range sto.shardPrefixes { shardSto, err := ld.GetStorage(prefix) if err != nil { return nil, err } sto.shards[i] = shardSto } return sto, nil }
func buildStorageForReceive(ld blobserver.Loader, confOrString interface{}) (storageFunc, os.Error) { // Static configuration from a string if s, ok := confOrString.(string); ok { sto, err := ld.GetStorage(s) if err != nil { return nil, err } f := func(io.Reader) (blobserver.Storage, []byte, os.Error) { return sto, nil, nil } return f, nil } conf := jsonconfig.Obj(confOrString.(map[string]interface{})) ifStr := conf.RequiredString("if") // TODO: let 'then' and 'else' point to not just strings but either // a string or a JSON object with another condition, and then // call buildStorageForReceive on it recursively thenTarget := conf.RequiredString("then") elseTarget := conf.RequiredString("else") if err := conf.Validate(); err != nil { return nil, err } thenSto, err := ld.GetStorage(thenTarget) if err != nil { return nil, err } elseSto, err := ld.GetStorage(elseTarget) if err != nil { return nil, err } switch ifStr { case "isSchema": return isSchemaPicker(thenSto, elseSto), nil } return nil, fmt.Errorf("cond: unsupported 'if' type of %q", ifStr) }
func newPublishFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) { pub := &PublishHandler{} pub.RootName = conf.RequiredString("rootName") blobRoot := conf.RequiredString("blobRoot") searchRoot := conf.RequiredString("searchRoot") cachePrefix := conf.OptionalString("cache", "") if err = conf.Validate(); err != nil { return } if pub.RootName == "" { return nil, os.NewError("invalid empty rootName") } bs, err := ld.GetStorage(blobRoot) if err != nil { return nil, fmt.Errorf("publish handler's blobRoot of %q error: %v", blobRoot, err) } pub.Storage = bs si, err := ld.GetHandler(searchRoot) if err != nil { return nil, fmt.Errorf("publish handler's searchRoot of %q error: %v", searchRoot, err) } pub.Search = si.(*search.Handler) if cachePrefix != "" { bs, err := ld.GetStorage(cachePrefix) if err != nil { return nil, fmt.Errorf("publish handler's cache of %q error: %v", cachePrefix, err) } pub.Cache = bs } return pub, nil }
func newUiFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err os.Error) { ui := &UIHandler{} ui.BlobRoot = conf.OptionalString("blobRoot", "") ui.SearchRoot = conf.OptionalString("searchRoot", "") ui.JSONSignRoot = conf.OptionalString("jsonSignRoot", "") pubRoots := conf.OptionalList("publishRoots") cachePrefix := conf.OptionalString("cache", "") if err = conf.Validate(); err != nil { return } ui.PublishRoots = make(map[string]*PublishHandler) for _, pubRoot := range pubRoots { h, err := ld.GetHandler(pubRoot) if err != nil { return nil, fmt.Errorf("UI handler's publishRoots references invalid %q", pubRoot) } pubh, ok := h.(*PublishHandler) if !ok { return } ui.PublishRoots[pubRoot] = pubh } checkType := func(key string, htype string) { v := conf.OptionalString(key, "") if v == "" { return } ct := ld.GetHandlerType(v) if ct == "" { err = fmt.Errorf("UI handler's %q references non-existant %q", key, v) } else if ct != htype { err = fmt.Errorf("UI handler's %q references %q of type %q; expected type %q", key, v, ct, htype) } } checkType("searchRoot", "search") checkType("jsonSignRoot", "jsonsign") if err != nil { return } if ui.BlobRoot != "" { bs, err := ld.GetStorage(ui.BlobRoot) if err != nil { return nil, fmt.Errorf("UI handler's blobRoot of %q error: %v", ui.BlobRoot, err) } ui.Storage = bs } if cachePrefix != "" { bs, err := ld.GetStorage(cachePrefix) if err != nil { return nil, fmt.Errorf("UI handler's cache of %q error: %v", cachePrefix, err) } ui.Cache = bs } if ui.SearchRoot != "" { h, _ := ld.GetHandler(ui.SearchRoot) ui.Search = h.(*search.Handler) } ui.staticHandler = http.FileServer(uiFiles) return ui, nil }