Skip to content
This repository was archived by the owner on Mar 6, 2024. It is now read-only.

Commit 475741a

Browse files
author
Nikola Vladimirov Iliev
committed
Add ui extensions commands
Following commads are added: generate, list, deploy, delete. They will help the user to manage his ui extensions. CLI Spinner class is implemented to indicate the action of the user. Extension generator is class which inherits generator abstract class and give the ability to copy existing template from the file system, of the user, and populate it with the data, given by the user. Prompt and PromptLauncher classes are build on top of python click lib to give the ability to validate and collect the data from the user. Signed-off-by: Nikola Vladimirov Iliev <nvladimirovi@vmware.com>
1 parent bbef5ad commit 475741a

22 files changed

+1094
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ docs/_build/
6060
target/
6161

6262
.idea/
63+
.vscode/
6364

6465
docs/.bundle
6566
docs/_site

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ python:
66
install:
77
- pip install git+https://github.com/vmware/pyvcloud.git
88
- pip install -r requirements.txt
9+
- pip install -e .
910
- python setup.py install
1011
- pip install tox
1112

tests/run-tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ D=`dirname $0`
66
$D/tenant-onboard.sh
77
$D/tenant-operations.sh
88
$D/cleanup.sh
9+
$D/ui-ext-test.sh

tests/ui-ext-test.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
VCD="C:\Users\nvladimirovi\AppData\Roaming\Python\Python36\Scripts\vcd.exe"
6+
VCD_UI_EXT_ABS_PATH=D:/test-py-cli/ui_plugin
7+
VCD_HOST=bos1-vcd-sp-static-198-58.eng.vmware.com
8+
VCD_ORG=System
9+
VCD_USER=administrator
10+
VCD_PASSWORD='********'
11+
12+
# $VCD login $VCD_HOST $VCD_ORG $VCD_USER --password $VCD_PASSWORD
13+
14+
$VCD version
15+
16+
echo 'This should deploy ui extension'
17+
$VCD uiext deploy --path $VCD_UI_EXT_ABS_PATH -p -pr
18+
echo 'This should list all ui extensions'
19+
$VCD uiext list
20+
echo 'This should delete all ui extensions'
21+
$VCD uiext delete -a
22+
echo 'This list command should print "There are no UI Extensions..." in the command line'
23+
$VCD uiext list

utilities/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from utilities.colors import Colors

utilities/colors.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from enum import Enum
2+
3+
Colors = Enum('Colors', {
4+
'HEADER': '\033[95m',
5+
'OKBLUE': '\033[94m',
6+
'OKGREEN': '\033[92m',
7+
'WARNING': '\033[93m',
8+
'FAIL': '\033[91m',
9+
'ENDC': '\033[0m',
10+
'BOLD': '\033[1m',
11+
'UNDERLINE': '\033[4m'
12+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from utilities.ui_ext.cli_spinners.cli_spinner import CliSpinner
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import threading
2+
import time
3+
import sys
4+
from enum import Enum
5+
6+
Spinners = Enum('Spinners', {
7+
"line": {
8+
"interval": 130,
9+
"frames": [
10+
"-",
11+
"\\",
12+
"|",
13+
"/"
14+
]
15+
},
16+
"dots": {
17+
"interval": 500,
18+
"frames": [
19+
".",
20+
"..",
21+
"..."
22+
]
23+
}
24+
})
25+
26+
27+
def backspace(n):
28+
# print((b'\x08').decode(), end='') # use \x08 char to go back
29+
print('\r', end='')
30+
31+
32+
class CliSpinner:
33+
"""CliSpinner library.
34+
Attributes
35+
----------
36+
CLEAR_LINE : str
37+
Code to clear the line
38+
"""
39+
CLEAR_LINE = '\033[K'
40+
41+
def __init__(self, text=None, spinner='dots', placement='left',
42+
stream=sys.stdout):
43+
"""Constructs the CliSpinner object.
44+
Parameters
45+
----------
46+
text : str, optional
47+
Text to display while spinning.
48+
spinner : str|dict, optional
49+
String or dictionary representing spinner. String can be one
50+
of 2 spinners supported.
51+
placement: str, optional
52+
Side of the text to place the spinner on. Can be `left` or `right`.
53+
Defaults to `left`.
54+
stream : io, optional
55+
Output.
56+
"""
57+
self._spinner = Spinners[spinner].value
58+
self.text = text
59+
self._stop_spinner = None
60+
self._interval = self._spinner['interval']
61+
self._stream = stream
62+
self._frame_index = 0
63+
self._placement = placement
64+
65+
def clear(self):
66+
"""Clears the line and returns cursor to the start.
67+
of line
68+
Returns
69+
-------
70+
self
71+
"""
72+
self._stream.write('\r')
73+
self._stream.write(self.CLEAR_LINE)
74+
75+
return self
76+
77+
def _frame(self):
78+
"""Builds and returns the frame to be rendered
79+
Returns
80+
-------
81+
frame
82+
"""
83+
frame = self._spinner['frames'][self._frame_index]
84+
self._frame_index += 1
85+
86+
if self._frame_index == len(self._spinner['frames']):
87+
self._frame_index = 0
88+
89+
return frame
90+
91+
def _render_frame(self):
92+
"""Renders the frame on the line after clearing it.
93+
"""
94+
frame = self._frame()
95+
96+
if self.text is not None:
97+
output = u'{0} {1}'.format(*[
98+
(self.text, frame)
99+
if self._placement == 'right' else
100+
(frame, self.text)
101+
][0])
102+
else:
103+
output = '{0}'.format(frame)
104+
self._stream.write(output)
105+
backspace(len(output))
106+
107+
def _render(self):
108+
"""Runs the render until thread flag is set.
109+
Returns
110+
-------
111+
self
112+
"""
113+
while not self._stop_spinner.is_set():
114+
self._render_frame()
115+
time.sleep(0.001 * self._interval)
116+
117+
return self
118+
119+
def start(self, text=None):
120+
"""Starts the spinner on a separate thread.
121+
Parameters
122+
----------
123+
text : None, optional
124+
Text to be used alongside spinner
125+
Returns
126+
-------
127+
self
128+
"""
129+
if text is not None:
130+
self.text = text
131+
132+
self._stop_spinner = threading.Event()
133+
self._spinner_thread = threading.Thread(target=self._render)
134+
self._spinner_thread.setDaemon(True)
135+
self._render_frame()
136+
self._spinner_id = self._spinner_thread.name
137+
self._spinner_thread.start()
138+
139+
return self
140+
141+
def stop(self, message=None):
142+
"""Stops the spinner and clears the line.
143+
Returns
144+
-------
145+
self
146+
"""
147+
if self._spinner_thread:
148+
self._stop_spinner.set()
149+
self._spinner_thread.join()
150+
151+
self._frame_index = 0
152+
self._spinner_id = None
153+
self.clear()
154+
155+
if message is not None:
156+
print(message)
157+
158+
return self
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from utilities.ui_ext.ext_generator.generator import Generator
2+
from utilities.ui_ext.ext_generator.ext_generator import ExtGenerator

0 commit comments

Comments
 (0)