瀏覽代碼

stackdriver: ux for config page, docs updated

Daniel Lee 7 年之前
父節點
當前提交
b8231b2903

+ 6 - 3
docs/sources/features/datasources/stackdriver.md

@@ -12,7 +12,7 @@ weight = 11
 
 # Using Google Stackdriver in Grafana
 
-Grafana ships with built in support for Google Stackdriver. You just have to add it as a datasource and you will be ready to build dashboards for your Stackdriver metrics.
+Grafana ships with built-in support for Google Stackdriver. You just have to add it as a datasource and you will be ready to build dashboards for your Stackdriver metrics.
 
 ## Adding the data source to Grafana
 
@@ -56,11 +56,14 @@ Click on the links above and click the `Enable` button:
 3. On the `Create service account key` page, choose key type `JSON`. Then in the `Service Account` dropdown, choose the `New service account` option:
 
     ![Create service account key](/img/docs/v54/stackdriver_create_service_account_key.png)
-4. Some new fields will appear. Fill in a name for the service account in the `Service account name` field and then choose the Monitoring Viewer role from the `Role` dropdown:
+4. Some new fields will appear. Fill in a name for the service account in the `Service account name` field and then choose the `Monitoring Viewer` role from the `Role` dropdown:
 
     ![Choose role](/img/docs/v54/stackdriver_service_account_choose_role.png)
 5. Click the Create button. A Json Web Token (JWT) file will be created and downloaded to your computer. Store this file in a secure place as it allows access to your Stackdriver data.
-6. Upload it to Grafana on the datasource Configuration page.
+6. Upload it to Grafana on the datasource Configuration page. You can either upload the file or paste in the contents of the file.
+     ![Choose role](/img/docs/v54/stackdriver_grafana_upload_key.png)
+7. The file contents will be encrypted and saved in the Grafana database. Don't forget to save after uploading the file!
+     ![Choose role](/img/docs/v54/stackdriver_grafana_key_uploaded.png)
 
 ## Metric Query Editor
 

+ 4 - 46
public/app/plugins/datasource/stackdriver/config_ctrl.ts

@@ -5,25 +5,20 @@ export class StackdriverConfigCtrl {
   jsonText: string;
   validationErrors: string[] = [];
   inputDataValid: boolean;
-  defaultProject: string;
-  projectsError: string;
-  projects: any[];
-  loadingProjects: boolean;
 
   /** @ngInject */
-  constructor(private $scope, datasourceSrv) {
+  constructor(datasourceSrv) {
     this.datasourceSrv = datasourceSrv;
     this.current.jsonData = this.current.jsonData || {};
     this.current.secureJsonData = this.current.secureJsonData || {};
     this.current.secureJsonFields = this.current.secureJsonFields || {};
-    this.defaultProject = this.current.jsonData.defaultProject;
-    this.projects = [];
   }
 
   save(jwt) {
     this.current.secureJsonData.privateKey = jwt.private_key;
     this.current.jsonData.tokenUri = jwt.token_uri;
     this.current.jsonData.clientEmail = jwt.client_email;
+    this.current.jsonData.defaultProject = jwt.project_id;
   }
 
   validateJwt(jwt) {
@@ -43,16 +38,15 @@ export class StackdriverConfigCtrl {
     if (this.validationErrors.length === 0) {
       this.inputDataValid = true;
       return true;
-    } else {
-      return false;
     }
+
+    return false;
   }
 
   onUpload(json) {
     this.jsonText = '';
     if (this.validateJwt(json)) {
       this.save(json);
-      this.displayProjects();
     }
   }
 
@@ -61,7 +55,6 @@ export class StackdriverConfigCtrl {
       const json = JSON.parse(e.originalEvent.clipboardData.getData('text/plain') || this.jsonText);
       if (this.validateJwt(json)) {
         this.save(json);
-        this.displayProjects();
       }
     } catch (error) {
       this.resetValidationMessages();
@@ -73,44 +66,9 @@ export class StackdriverConfigCtrl {
     this.validationErrors = [];
     this.inputDataValid = false;
     this.jsonText = '';
-    this.loadingProjects = false;
-    this.projectsError = '';
 
     this.current.jsonData = {};
     this.current.secureJsonData = {};
     this.current.secureJsonFields = {};
   }
-
-  async displayProjects() {
-    if (this.projects.length === 0) {
-      try {
-        this.loadingProjects = true;
-        const ds = await this.datasourceSrv.loadDatasource(this.current.name);
-        this.projects = await ds.getProjects();
-        this.$scope.$apply(() => {
-          if (this.projects.length > 0) {
-            this.current.jsonData.defaultProject = this.current.jsonData.defaultProject || this.projects[0].id;
-          }
-        });
-      } catch (error) {
-        let message = 'Projects cannot be fetched: ';
-        message += error.statusText ? error.statusText + ': ' : '';
-        if (error && error.data && error.data.error && error.data.error.message) {
-          if (error.data.error.code === 403) {
-            message += `
-            A list of projects could not be fetched from the Google Cloud Resource Manager API.
-            You might need to enable it first:
-            https://console.developers.google.com/apis/library/cloudresourcemanager.googleapis.com`;
-          } else {
-            message += error.data.error.code + '. ' + error.data.error.message;
-          }
-        } else {
-          message += 'Cannot connect to Stackdriver API';
-        }
-        this.$scope.$apply(() => (this.projectsError = message));
-      } finally {
-        this.$scope.$apply(() => (this.loadingProjects = false));
-      }
-    }
-  }
 }

+ 79 - 54
public/app/plugins/datasource/stackdriver/partials/config.html

@@ -1,59 +1,84 @@
-<div ng-if="!ctrl.current.jsonData.clientEmail && !ctrl.inputDataValid">
-	<div class="gf-form-group" ng-if="!ctrl.inputDataValid">
-		<div class="gf-form">
-			<form>
-				<dash-upload on-upload="ctrl.onUpload(dash)"></dash-upload>
-			</form>
-		</div>
-	</div>
-	<div class="gf-form-group">
-		<h5 class="section-heading" ng-if="!ctrl.inputDataValid">Or paste JSON</h5>
-		<div class="gf-form" ng-if="!ctrl.inputDataValid">
-			<textarea rows="10" data-share-panel-url="" class="gf-form-input" ng-model="ctrl.jsonText" ng-paste="ctrl.onPasteJwt($event)"></textarea>
-		</div>
-		<div ng-repeat="valError in ctrl.validationErrors" class="text-error p-l-1">
-			<i class="fa fa-warning"></i>
-			{{valError}}
-		</div>
-	</div>
+<div class="gf-form-group">
+  <div class="grafana-info-box">
+    <h5>GCP Service Account</h5>
+    <p>
+      To authenticate with the Stackdriver API, you need to create a Google Cloud Platform (GCP) Service Account for
+      the Project you want to show data for. A Grafana datasource integrates with one GCP Project. If you want to
+      visualize data from multiple GCP Projects then you need to create one datasource per GCP Project.
+    </p>
+    <p>
+      The <strong>Monitoring Viewer</strong> role provides all the permissions that Grafana needs.
+    </p>
+    <p>
+      The following APIs need to be enabled on GCP for the datasource to work:
+      <ul>
+        <li><a class="external-link" target="_blank" href="https://console.cloud.google.com/apis/library/monitoring.googleapis.com">Monitoring
+            API</a></li>
+        <li><a class="external-link" target="_blank" href="https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com">Resource
+            Manager API</a></li>
+      </ul>
+    </p>
+    <p>Detailed instructions on how to create a Service Account can be found <a class="external-link" target="_blank"
+        href="http://docs.grafana.org/datasources/stackdriver/">in
+        the documentation.</a></p>
+  </div>
+</div>
+
+<div class="gf-form-group">
+  <div class="gf-form">
+    <h3>Service Account Authentication</h3>
+    <info-popover mode="header">Upload your Service Account key file or paste in the contents of the file. The file
+      contents will be encrypted and saved in the Grafana database.</info-popover>
+  </div>
+
+  <div ng-if="!ctrl.current.jsonData.clientEmail && !ctrl.inputDataValid">
+    <div class="gf-form-group" ng-if="!ctrl.inputDataValid">
+      <div class="gf-form">
+        <form>
+          <dash-upload on-upload="ctrl.onUpload(dash)" btn-text="Upload Service Account key file"></dash-upload>
+        </form>
+      </div>
+    </div>
+    <div class="gf-form-group">
+      <h5 class="section-heading" ng-if="!ctrl.inputDataValid">Or paste Service Account key JSON</h5>
+      <div class="gf-form" ng-if="!ctrl.inputDataValid">
+        <textarea rows="10" data-share-panel-url="" class="gf-form-input" ng-model="ctrl.jsonText" ng-paste="ctrl.onPasteJwt($event)"></textarea>
+      </div>
+      <div ng-repeat="valError in ctrl.validationErrors" class="text-error p-l-1">
+        <i class="fa fa-warning"></i>
+        {{valError}}
+      </div>
+    </div>
+  </div>
 </div>
 
 <div class="gf-form-group" ng-if="ctrl.inputDataValid || ctrl.current.jsonData.clientEmail">
-	<div class="gf-form-inline">
-		<div class="gf-form">
-			<span class="gf-form-label width-9">Token URI</span>
-			<input class="gf-form-input width-30" disabled type="text" ng-model='ctrl.current.jsonData.tokenUri' />
-		</div>
-	</div>
-	<div class="gf-form-inline">
-		<div class="gf-form">
-			<span class="gf-form-label width-9">Client Email</span>
-			<input class="gf-form-input width-30" disabled type="text" ng-model="ctrl.current.jsonData.clientEmail" />
-		</div>
-	</div>
-	<div class="gf-form" ng-if="ctrl.current.secureJsonFields.privateKey">
-		<span class="gf-form-label width-9">Private Key</span>
-		<input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
-	</div>
+  <h6>Uploaded Key Details</h6>
 
+  <div class="gf-form">
+    <span class="gf-form-label width-9">Project</span>
+    <input class="gf-form-input width-40" disabled type="text" ng-model="ctrl.current.jsonData.defaultProject" />
+  </div>
+  <div class="gf-form">
+      <span class="gf-form-label width-9">Client Email</span>
+      <input class="gf-form-input width-40" disabled type="text" ng-model="ctrl.current.jsonData.clientEmail" />
+    </div>
+  <div class="gf-form">
+    <span class="gf-form-label width-9">Token URI</span>
+    <input class="gf-form-input width-40" disabled type="text" ng-model='ctrl.current.jsonData.tokenUri' />
+  </div>
+  <div class="gf-form" ng-if="ctrl.current.secureJsonFields.privateKey">
+    <span class="gf-form-label width-9">Private Key</span>
+    <input type="text" class="gf-form-input max-width-12" disabled="disabled" value="configured">
+  </div>
+
+  <div class="gf-form width-18">
+    <a class="btn btn-secondary gf-form-btn" href="#" ng-click="ctrl.resetValidationMessages()">Reset Service
+      Account Key </a>
+    <info-popover mode="right-normal">
+      Reset to clear the uploaded key and upload a new file.
+    </info-popover>
+  </div>
+</div>
 
-	<div class="gf-form">
-		<a class="btn btn-secondary gf-form-btn" href="#" ng-click="ctrl.resetValidationMessages()">Reset form</a>
-	</div>
-	<br />
-	<div class="gf-form">
-		<span class="gf-form-label width-10">Default Project</span>
-		<div class="gf-form-select-wrapper max-width-23">
-			<select class="gf-form-input" ng-model="ctrl.current.jsonData.defaultProject" ng-options="p.id as p.name for p in ctrl.projects"
-			 ng-change="ctrl.userChangedDefaultProject()"></select>
-		</div>
-		<div ng-if="ctrl.loadingProjects">
-			<i class="fa fa-spinner fa-spin"></i>
-			<em>Fetching projects...&hellip;</em>
-		</div>
-	</div>
-	<div ng-if="ctrl.projectsError" class="text-error p-l-1">
-		<i class="fa fa-warning"></i>
-		{{ctrl.projectsError}}
-	</div>
-</div>
+<p class="gf-form-label" ng-hide="ctrl.current.secureJsonFields.privateKey"><i class="fa fa-save"></i> Do not forget to save your changes after uploading a file.</p>