#azure-sdk #azure-rest #cloud #iot #api-bindings

azure_sdk_for_rust

Rust封装的Microsoft Azure REST API

26个不稳定版本 (11个破坏性更新)

0.12.0 2019年6月1日
0.11.0 2019年3月12日
0.10.3 2018年12月22日
0.10.0 2018年8月26日
0.1.3 2016年2月5日

#212 in #iot

每月33次下载

Apache-2.0

620KB
16K SLoC

微软Azure SDK for Rust

docs

legal

Build Status Coverage Status stability-unstable

Crate cratedown cratelastdown

tag release commitssince

GitHub contributors

简介

微软Azure通过REST API公开其技术。这些API易于从任何语言中消费(优点),但类型较弱。使用这个库及其相关的crate,您可以用一种符合Rust风格的方式利用微软Azure的功能。

此crate严重依赖名为Hyper的出色crate。截至本库版本0.4.0,所有方法都是未来感知的。

从版本0.8.0的Cosmos和0.9.0的Storage开始,仓库开始采用builder模式。截至0.10.0,大多数存储API已迁移到builder模式,但仍有方法缺失。请检查相关问题以跟踪更新过程。这仍然是一个进行中的过渡,但生成的API要容易使用得多。此外,大多数检查都已移动到编译时。遗憾的是,这些更改不是向后兼容的。我在这里记录了我的方法:https://dev.to/mindflavor/rust-builder-pattern-with-types-3chf

从版本0.12.0开始,库从hyper-tls切换到hyper-rustls,这是bmc-msft在问题#120中建议的。这应该允许库实现100%的rust。

注意:此仓库正在积极开发中,可能会在一段时间内出现故障。当前版本可能包含错误。如往常一样,如果发现问题,请提交问题。

免责声明

尽管我是微软员工,但这不是一个微软认可的项目。这仅仅是我个人的项目:我喜欢Rust(谁不喜欢呢?😏)以及微软Azure技术,所以我想弥合它们之间的差距。这也是学习Rust的好项目。此库严重依赖于Hyper。我们使用最新的Hyper代码,因此此库完全异步,具有Futures和Tokio。

示例

您可以在examples文件夹中找到示例。这里是一瞥:

main.rs

extern crate azure_sdk_for_rust;

extern crate chrono;
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
extern crate tokio;
extern crate tokio_core;

use std::error::Error;

use futures::future::*;
use tokio_core::reactor::Core;

use azure_sdk_for_rust::cosmos::{AuthorizationToken, Client, TokenType};

#[macro_use]
extern crate serde_derive;
use azure_sdk_for_rust::cosmos;

#[derive(Serialize, Deserialize, Debug)]
struct MySampleStruct<'a> {
    id: &'a str,
    a_string: &'a str,
    a_number: u64,
    a_timestamp: i64,
}

// Following the official azure cosmos db tutorial: https://docs.microsoft.com/pt-br/azure/cosmos-db/sql-api-dotnetcore-get-started
// Master key is the Primary Key from Keys section in your CosmosDB screen
// Account is the first part of URI from Keys section, if your URI is  https://test.documents.azure.com:443/ the account is test
// DATABASES are the base objects in your Data Explorer section
// COLLECTIONS are the objects inside the DATABASES

const DATABASE: &'static str = "azuresdktestdb";
const COLLECTION: &'static str = "azuresdktc";

fn main() {
    code().unwrap();
}

// This code will perform these tasks:
// 1. Find an Azure Cosmos DB called *DATABASE*. If it does not exist, create it.
// 2. Find an Azure Cosmos collection called *COLLECTION* in *DATABASE*.
//      If it does not exist, create it.
// 3. Store an entry in collection *COLLECTION* of database *DATABASE*.
// 4. Delete everything.
//
// We will use multiple futures for this hoping to make the code clearer.
// There is no need to proceed this way in your code.
// You can go crazy with future combinators if you want to :)
fn code() -> Result<(), Box<Error>> {
    // Let's get Cosmos account and master key from env variables.
    // This helps automated testing.
    let master_key =
        std::env::var("COSMOSDB_MASTER_KEY").expect("Set env variable COSMOS_MASTER_KEY first!");
    let account =
        std::env::var("COSMOSDB_ACCOUNT").expect("Set env variable COSMOS_ACCOUNT first!");

    // First, we create an authorization token. There are two types of tokens, master and resource
    // constrained. Please check the Azure documentation for details. You can change tokens
    // at will and it's a good practice to raise your privileges only when needed.
    let authorization_token = AuthorizationToken::new(account, TokenType::Master, &master_key)?;

    // We will create a tokio-core reactor which will drive our futures.
    let mut core = Core::new()?;

    // Next we will create a Cosmos client. You need an authorization_token but you can later
    // change it if needed. Notice the client will be tied to your reactor.
    let client = Client::new(authorization_token)?;

    // list_databases will give us the databases available in our account. If there is
    // an error (for example, the given key is not valid) you will receive a
    // specific AzureError. In this example we will look for a specific database
    // so we chain a filter operation.
    let future = client
        .list_databases()
        .and_then(|databases| ok(databases.into_iter().find(|db| db.id == DATABASE)));

    // Now we run the future and check the answer. If the requested database
    // is not found we create it.
    let database = match core.run(future)? {
        Some(db) => db,
        None => core.run(client.create_database(DATABASE))?,
    };
    println!("database == {:?}", database);

    // Now we look for a specific collection. If is not already present
    // we will create it. The collection creation is more complex and
    // has many options (such as indexing and so on).
    let collection = {
        let collections = core.run(client.list_collections(&DATABASE))?;

        if let Some(collection) = collections.into_iter().find(|coll| coll.id == COLLECTION) {
            collection
        } else {
            let indexes = cosmos::collection::IncludedPathIndex {
                kind: cosmos::collection::KeyKind::Hash,
                data_type: cosmos::collection::DataType::String,
                precision: Some(3),
            };

            let ip = cosmos::collection::IncludedPath {
                path: "/*".to_owned(),
                indexes: vec![indexes],
            };

            let ip = cosmos::collection::IndexingPolicy {
                automatic: true,
                indexing_mode: cosmos::collection::IndexingMode::Consistent,
                included_paths: vec![ip],
                excluded_paths: vec![],
            };

            let coll = cosmos::collection::Collection::new(COLLECTION, ip);
            // Notice here we specify the expected performance level.
            // Performance levels have price impact. Also, higher
            // performance levels force you to specify an indexing
            // strategy. Consult the documentation for more details.
            core.run(client.create_collection(&DATABASE, 400, &coll))?
        }
    };

    println!("collection = {:?}", collection);

    // Now that we have a database and a collection we can insert
    // data in them. Let's create a struct. The only constraint
    // is that the struct should be Serializable.
    let doc = MySampleStruct {
        id: "unique_id1",
        a_string: "Something here",
        a_number: 100,
        a_timestamp: chrono::Utc::now().timestamp(),
    };

    // Now we store the struct in Azure Cosmos DB.
    // Notice how easy it is! :)
    // The method create_document will return, upon success,
    // the document attributes.
    let document_attributes = core.run(
        client
            .create_document(&DATABASE, &COLLECTION, &doc)
            .execute(),
    )?;
    println!("document_attributes == {:?}", document_attributes);

    // We will perform some cleanup. First we delete the collection...
    core.run(client.delete_collection(DATABASE, &COLLECTION))?;
    println!("collection deleted");

    // And then we delete the database.
    core.run(client.delete_database(DATABASE))?;
    println!("database deleted");

    Ok(())
}

最先进的技术

目前,关键框架已经到位(身份验证、枚举、解析等)。如果您想贡献,请随时!方法每天都在增加,请检查发布页面以获取进度更新。请注意,该项目处于早期阶段,因此API可能会随时更改。我会努力保持稳定,但因为我刚接触Rust,我肯定在不久的将来需要纠正一些严重的错误😄。我通常为最新的夜间版本构建,并让Travis检查向后兼容性。

贡献

如果您想贡献,请随时!无需拘泥于形式!😉。请注意,提出拉取请求表示您同意按照Apache许可证,版本2.0将您的代码作为贡献。

实现的方法

存储容器

方法 URL 构建器模式
创建容器 https://docs.microsoft.com/en-us/rest/api/storageservices/create-container
列出容器 https://docs.microsoft.com/en-us/rest/api/storageservices/list-containers2
删除容器 https://docs.microsoft.com/en-us/rest/api/storageservices/delete-container
获取ACL https://docs.microsoft.com/en-us/rest/api/storageservices/get-container-acl
设置ACL https://docs.microsoft.com/en-us/rest/api/storageservices/set-container-acl
获取属性 https://docs.microsoft.com/en-us/rest/api/storageservices/get-container-properties
获取租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-container
中断租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-container
释放租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-container
更新租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-container

存储Blob

方法 URL 构建器模式
列出Blob https://docs.microsoft.com/en-us/rest/api/storageservices/list-blobs
获取Blob https://docs.microsoft.com/en-us/rest/api/storageservices/get-blob
放置块Blob https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob
放置页Blob https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob
放置追加Blob https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob
放置Blob页 https://docs.microsoft.com/en-us/rest/api/storageservices/put-page 是(作为update_page
清除Blob页 https://docs.microsoft.com/en-us/rest/api/storageservices/put-page 是(作为clear_page
放置块 https://docs.microsoft.com/en-us/rest/api/storageservices/put-block
获取块列表 https://docs.microsoft.com/en-us/rest/api/storageservices/get-block-list
放置块列表 https://docs.microsoft.com/en-us/rest/api/storageservices/put-block-list
获取Blob租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-blob
更新Blob租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-blob
更改Blob租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-blob
释放Blob租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-blob
中断Blob租约 https://docs.microsoft.com/en-us/rest/api/storageservices/lease-blob
删除Blob https://docs.microsoft.com/en-us/rest/api/storageservices/delete-blob

事件中心

方法 URL
发送事件 https://msdn.microsoft.com/en-us/library/azure/dn790664.aspx

Cosmos数据库

数据库
方法 URL
创建数据库 https://docs.microsoft.com/en-us/rest/api/documentdb/create-a-database
列出数据库 https://docs.microsoft.com/en-us/rest/api/documentdb/list-databases
获取数据库 https://docs.microsoft.com/en-us/rest/api/documentdb/get-a-database
删除数据库 https://docs.microsoft.com/en-us/rest/api/documentdb/delete-a-database1
集合
方法 URL
创建集合 https://docs.microsoft.com/en-us/rest/api/documentdb/create-a-collection
列出集合 https://docs.microsoft.com/en-us/rest/api/documentdb/list-collections
获取集合 https://docs.microsoft.com/en-us/rest/api/documentdb/get-a-collection
删除集合 https://docs.microsoft.com/en-us/rest/api/documentdb/delete-a-collection
替换集合 https://docs.microsoft.com/en-us/rest/api/documentdb/replace-a-collection
文档
方法 URL
创建文档 https://docs.microsoft.com/en-us/rest/api/documentdb/create-a-document
列出文档 https://docs.microsoft.com/en-us/rest/api/documentdb/list-documents
获取文档 https://docs.microsoft.com/en-us/rest/api/documentdb/get-a-document
查询文档 https://docs.microsoft.com/en-us/rest/api/documentdb/query-documents
替换文档 https://docs.microsoft.com/en-us/rest/api/cosmos-db/replace-a-document
删除文档 https://docs.microsoft.com/en-us/rest/api/cosmos-db/delete-a-document

Azure表

方法 URL
创建表 https://docs.microsoft.com/en-us/rest/api/storageservices/create-table
查询表 https://docs.microsoft.com/en-us/rest/api/storageservices/query-tables
查询实体 https://docs.microsoft.com/en-us/rest/api/storageservices/query-entities
插入实体 https://docs.microsoft.com/en-us/rest/api/storageservices/insert-entity
更新实体 https://docs.microsoft.com/en-us/rest/api/storageservices/update-entity2
删除实体 https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1

Azure 表实体可以批量操作。实体以 JSON 格式序列化。

运行端到端测试

Linux

export STORAGE_ACCOUNT=<account>
export STORAGE_MASTER_KEY=<key>

export AZURE_SERVICE_BUS_NAMESPACE=<azure_service_bus_namespace>
export AZURE_EVENT_HUB_NAME=<azure_event_hub_name>
export AZURE_POLICY_NAME=<azure_policy_name>
export AZURE_POLICY_KEY=<azure policy key>

cargo test --features=test_e2e

Windows

set STORAGE_ACCOUNT=<account>
set STORAGE_MASTER_KEY=<key>

set AZURE_SERVICE_BUS_NAMESPACE=<azure_service_bus_namespace>
set AZURE_EVENT_HUB_NAME=<azure_event_hub_name>
set AZURE_POLICY_NAME=<azure_policy_name>
set AZURE_POLICY_KEY=<azure policy key>

cargo test --features=test_e2e

许可协议

本项目采用 Apache 许可协议,版本 2.0 发布。

依赖项

~22MB
~515K SLoC