Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 34082ffa5f753ebc686984016b9ec0d95a3ca2bd @richorama committed Nov 30, 2013
Showing with 346 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +63 −0 azure-table-backup.njsproj
  3. +22 −0 azure-table-backup.sln
  4. +3 −0 bin/AzureTableBackup
  5. +1 −0 bin/AzureTableBackup.js
  6. +162 −0 index.js
  7. +20 −0 license.txt
  8. +31 −0 package.json
  9. +42 −0 readme.md
@@ -0,0 +1,2 @@
+node_modules
+*.suo
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{79babbea-d5c8-4d1e-b4b1-e0395fe044ee}</ProjectGuid>
+ <ProjectHome />
+ <ProjectView>ProjectFiles</ProjectView>
+ <StartupFile>index.js</StartupFile>
+ <WorkingDirectory>.</WorkingDirectory>
+ <OutputPath>.</OutputPath>
+ <ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
+ <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
+ <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
+ <PropertyGroup Condition="'$(Configuration)' == 'Release'" />
+ <ItemGroup>
+ <Content Include="package.json" />
+ <Compile Include="index.js" />
+ </ItemGroup>
+ <ItemGroup />
+ <Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
+ <ProjectExtensions>
+ <VisualStudio>
+ <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
+ <WebProjectProperties>
+ <UseIIS>False</UseIIS>
+ <AutoAssignPort>True</AutoAssignPort>
+ <DevelopmentServerPort>0</DevelopmentServerPort>
+ <DevelopmentServerVPath>/</DevelopmentServerVPath>
+ <IISUrl>http://localhost:48022/</IISUrl>
+ <NTLMAuthentication>False</NTLMAuthentication>
+ <UseCustomServer>True</UseCustomServer>
+ <CustomServerUrl>http://localhost:1337</CustomServerUrl>
+ <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
+ </WebProjectProperties>
+ </FlavorProperties>
+ <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}" User="">
+ <WebProjectProperties>
+ <StartPageUrl>
+ </StartPageUrl>
+ <StartAction>CurrentPage</StartAction>
+ <AspNetDebugging>True</AspNetDebugging>
+ <SilverlightDebugging>False</SilverlightDebugging>
+ <NativeDebugging>False</NativeDebugging>
+ <SQLDebugging>False</SQLDebugging>
+ <ExternalProgram>
+ </ExternalProgram>
+ <StartExternalURL>
+ </StartExternalURL>
+ <StartCmdLineArguments>
+ </StartCmdLineArguments>
+ <StartWorkingDirectory>
+ </StartWorkingDirectory>
+ <EnableENC>False</EnableENC>
+ <AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
+ </WebProjectProperties>
+ </FlavorProperties>
+ </VisualStudio>
+ </ProjectExtensions>
+</Project>
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "azure-table-backup", "azure-table-backup.njsproj", "{79BABBEA-D5C8-4D1E-B4B1-E0395FE044EE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {79BABBEA-D5C8-4D1E-B4B1-E0395FE044EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {79BABBEA-D5C8-4D1E-B4B1-E0395FE044EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {79BABBEA-D5C8-4D1E-B4B1-E0395FE044EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {79BABBEA-D5C8-4D1E-B4B1-E0395FE044EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
@@ -0,0 +1,3 @@
+#!/usr/bin/env node
+
+require('./AzureTableBackup.js');
@@ -0,0 +1 @@
+require('../index.js');
@@ -0,0 +1,162 @@
+var azure = require('azure');
+var Lazy = require('lazy');
+var fs = require('fs');
+var args = require('args');
+
+var options = args.Options.parse([
+ {
+ name: 'action',
+ shortName: 'a',
+ required: true,
+ help: 'The action to perform (backup / restore / list)'
+ },
+ {
+ name: 'name',
+ shortName: 'n',
+ required: true,
+ help: 'The name of the Windows Azure Storage Account'
+ },
+ {
+ name: 'key',
+ shortName: 'k',
+ required: true,
+ help: 'The key of the Windows Azure Storage Account'
+ },
+ {
+ name: 'table',
+ shortName: 't',
+ help: 'The table in Windows Azure Storage to back up'
+ },
+ {
+ name: 'file',
+ shortName: 'f',
+ help: 'Filename to use as backup or restore (defaults to the table name)'
+ },
+]);
+
+
+var parsed;
+try {
+ parsed = args.parser(process.argv).parse(options);
+}
+catch (err) {
+ console.log(options.getHelp());
+ return;
+}
+
+var tableService = azure.createTableService(parsed.name, parsed.key);
+
+switch (parsed.action){
+ case "backup":
+ if (!parsed.table){
+ console.log("use must supply a table name");
+ break;
+ }
+ backupEntities(parsed.table, parsed.file || parsed.table + ".json");
+ break;
+ case "restore":
+ if (!parsed.table){
+ console.log("use must supply a table name");
+ break;
+ }
+ restoreEntities(parsed.table, parsed.file || parsed.table + ".json");
+ break;
+ case "list":
+ listTables();
+ break;
+ default:
+ console.log("action not recognised, please supply one of (backup / restore / list)");
+}
+
+function listTables(){
+ console.log("querying tables\n");
+ tableService.queryTables(function(err, tables){
+ if (err){
+ console.log(err);
+ }
+ tables.forEach(function(x){
+ console.log(x.TableName);
+ });
+ });
+}
+var counter = 0;
+function queryEntities(table, cb, finished) {
+ counter = 0;
+ console.log("downloading entities\n");
+
+ var query = azure.TableQuery
+ .select()
+ .from(table);
+
+ tableService.queryEntities(query, function(error, entities, continuationToken){
+ if (error){
+ console.log(error);
+ } else {
+ counter += entities.length;
+ entities.forEach(cb);
+ if (continuationToken.nextPartitionKey) {
+ pageResults(continuationToken, cb, finished);
+ } else {
+ if (finished){
+ finished();
+ }
+ }
+ }
+ });
+}
+
+function pageResults(continuationToken, cb, finished){
+ continuationToken.getNextPage(function(error, results, newContinuationToken){
+ if (error){
+ console.log(error);
+ } else {
+ counter += entities.length;
+ entities.forEach(cb);
+ if (newContinuationToken.nextPartitionKey){
+ pageResults(newContinuationToken, cb);
+ } else {
+ if (finished){
+ finished();
+ }
+ }
+ }
+ });
+}
+
+
+function backupEntities(table, filename){
+ var stream = fs.createWriteStream(filename)
+ queryEntities(table, function(x){
+ delete x._;
+ stream.write(JSON.stringify(x) + "\n");
+ }, function(){
+ stream.end();
+ console.log("saved " + counter + " entities");
+ });
+}
+
+
+function restoreEntities(table, filename){
+ var count = 0;
+ tableService.createTableIfNotExists(table, function(error){
+ if (error){
+ console.log(error);
+ } else {
+ var lazy = new Lazy(fs.createReadStream(filename));
+
+ lazy.on('end', function() { console.log("uploaded " + count + " entities"); })
+ .lines
+ .forEach(function(line){
+ count += 1;
+ var json = JSON.parse(line.toString());
+ console.log(json);
+ tableService.insertOrReplaceEntity(table, json, function(err){
+ if(err){
+ console.log(err);
+ }
+ });
+ });
+
+ }
+ });
+}
@@ -0,0 +1,20 @@
+Copyright 2013 Richard Astbury
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
+{
+ "name": "azuretablebackup",
+ "version": "0.0.1",
+ "description": "Command line tool to backup Windows Azure Table Storage",
+ "main": "index.js",
+ "preferGlobal": "true",
+ "bin": {
+ "AzureTableBackup": "AzureTableBackup.js"
+ },
+ "dependencies": {
+ "azure": "~0.7.18",
+ "args": "~0.0.3",
+ "lazy": "~1.0.11"
+ },
+ "devDependencies": {},
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "azure",
+ "table",
+ "backup",
+ "restore",
+ "json"
+ ],
+ "author": "Richard Astbury",
+ "license": "MIT",
+ "bin": {
+ "AzureTableBackup": "./bin/AzureTableBackup"
+ }
+}
@@ -0,0 +1,42 @@
+# Azure Table Backup
+
+A command line utility to backup and restore Windows Azure Table Storage.
+
+## Installation
+
+You must have Node.js installed first.
+
+```
+$ npm install azuretablebackup -g
+```
+
+## Usage
+
+Examples of usage:
+
+```
+// backup the foo table
+$ azuretablebackup -a backup -n mystorageaccount -k xxx -t foo
+
+// restore the foo table
+$ azuretablebackup -a restore -n mystorageaccount -k xxx -t foo
+
+// restore the foo backup to a new table
+$ azuretablebackup -a restore -n mystorageaccount -k xxx -t foo2 -f foo.json
+
+// list all available tables
+$ azuretablebackup -a list -n mystorageaccount -k xxx
+```
+
+Arguments:
+```
+--action, -a The action to perform (backup / restore / list), required
+--name, -n The name of the Windows Azure Storage Account, required
+--key, -k The key of the Windows Azure Storage Account, required
+--table, -t The table in Windows Azure Storage to back up
+--file, -f Filename to use as backup or restore (defaults to the table name)
+```
+
+## License
+
+MIT

0 comments on commit 34082ff

Please sign in to comment.