Open akatona1 opened 8 years ago
Hello @akatona1,
Thank you for the issue report! We renamed the examples folder and the docs didn't get updated too, great catch.
The samples can be found at https://github.com/tableau/document-api-python/tree/master/samples
.
Version 0.3 should have the ability to update a connection inside a workbook, though not all the attributes are exposed, and I think Hadoop's specifically are not yet.
Can you post a clean TWB file that has a hadoop connection, and an example of what you would want to update it to?
Hi @t8y8,
Thanks for the quick response. Unfortunately, I will not be able to upload anything. I can only provide the information that I gave above.
Alex
Here's an example of the connections element:
<connection authentication-type='2' class='hortonworkshadoophive' connection-type='2'
dbname='' odbc-connect-string-extras='' one-time-sql='' port='15000'
server='hadoophorton.test.tsi.lan' server-oauth='' username='' workgroup-auth-mode='as-is'>
We'll need to figure out what all the auth-types are and the connection-types so we can validate that they make sense.
@t8y8,
This seems to be the design of the auth-types and connection-types for the Hortonworks connection, where the auth-types are increasing from 0 to 8 and the connection type is 2 (for HiveServer2):
Auth-Type | Auth-Type XML code | Connection-Type XML code |
---|---|---|
No Authentication | 0 | 2 |
Kerberos | 1 | 2 |
User Name | 2 | 2 |
User Name and Password | 3 | 2 |
User Name and Password (SSL) | 4 | 2 |
Microsoft Azure HDInsight Emulator | 5 | 2 |
Microsoft Azure HDInsight Service | 6 | 2 |
HTTP | 7 | 2 |
HTTPS | 8 | 2 |
I was playing around with this and modified connection.py to read the fields I needed. Copying here in case it's useful. `import xml.etree.ElementTree as ET from tableaudocumentapi.dbclass import is_valid_dbclass
class Connection(object): """A class representing connections inside Data Sources."""
def __init__(self, connxml):
"""Connection is usually instantiated by passing in connection elements
in a Data Source. If creating a connection from scratch you can call
`from_attributes` passing in the connection attributes.
"""
self._connectionXML = connxml
self._dbname = connxml.get('dbname')
self._server = connxml.get('server')
self._username = connxml.get('username')
self._authentication = connxml.get('authentication')
self._class = connxml.get('class')
self._port = connxml.get('port', None)
self._query_band = connxml.get('query-band-spec', None)
self._initial_sql = connxml.get('one-time-sql', None)
#added for Hortonworks Hive connection
self._schema = connxml.get('schema', None)
self._http_path = connxml.get('http-path',None)
self._connection_type = connxml.get('connection-type',None)
self._sslcert = connxml.get('sslcert',None)
self._sslmode = connxml.get('sslmode',None)
def __repr__(self):
return "'<Connection server='{}' dbname='{}' @ {}>'".format(self._server, self._dbname, hex(id(self)))
@classmethod
def from_attributes(cls, server, dbname, username, dbclass, port=None, query_band=None,
initial_sql=None, authentication=''):
"""Creates a new connection that can be added into a Data Source.
defaults to `''` which will be treated as 'prompt' by Tableau."""
root = ET.Element('connection', authentication=authentication)
xml = cls(root)
xml.server = server
xml.dbname = dbname
xml.username = username
xml.dbclass = dbclass
xml.port = port
xml.query_band = query_band
xml.initial_sql = initial_sql
return xml
@property
def dbname(self):
"""Database name for the connection. Not the table name."""
return self._dbname
@dbname.setter
def dbname(self, value):
"""
Set the connection's database name property.
Args:
value: New name of the database. String.
Returns:
Nothing.
"""
self._dbname = value
self._connectionXML.set('dbname', value)
@property
def server(self):
"""Hostname or IP address of the database server. May also be a URL in some connection types."""
return self._server
@server.setter
def server(self, value):
"""
Set the connection's server property.
Args:
value: New server. String.
Returns:
Nothing.
"""
self._server = value
self._connectionXML.set('server', value)
@property
def username(self):
"""Username used to authenticate to the database."""
return self._username
@username.setter
def username(self, value):
"""
Set the connection's username property.
Args:
value: New username value. String.
Returns:
Nothing.
"""
self._username = value
self._connectionXML.set('username', value)
@property
def authentication(self):
return self._authentication
@property
def dbclass(self):
"""The type of connection (e.g. 'MySQL', 'Postgresql'). A complete list
can be found in dbclass.py"""
return self._class
@dbclass.setter
def dbclass(self, value):
"""Set the connection's dbclass property.
Args:
value: New dbclass value. String.
Returns:
Nothing.
"""
if not is_valid_dbclass(value):
raise AttributeError("'{}' is not a valid database type".format(value))
self._class = value
self._connectionXML.set('class', value)
@property
def port(self):
"""Port used to connect to the database."""
return self._port
@port.setter
def port(self, value):
"""Set the connection's port property.
Args:
value: New port value. String.
Returns:
Nothing.
"""
self._port = value
# If port is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['port']
except KeyError:
pass
else:
self._connectionXML.set('port', value)
@property
def query_band(self):
"""Query band passed on connection to database."""
return self._query_band
@query_band.setter
def query_band(self, value):
"""Set the connection's query_band property.
Args:
value: New query_band value. String.
Returns:
Nothing.
"""
self._query_band = value
# If query band is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['query-band-spec']
except KeyError:
pass
else:
self._connectionXML.set('query-band-spec', value)
@property
def initial_sql(self):
"""Initial SQL to be run."""
return self._initial_sql
@initial_sql.setter
def initial_sql(self, value):
"""Set the connection's initial_sql property.
Args:
value: New initial_sql value. String.
Returns:
Nothing.
"""
self._initial_sql = value
# If initial_sql is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['one-time-sql']
except KeyError:
pass
else:
self._connectionXML.set('one-time-sql', value)
@property
def schema(self):
"""Initial SQL to be run."""
return self._schema
@schema.setter
def schema(self, value):
"""Set the connection's initial_sql property.
Args:
value: New initial_sql value. String.
Returns:
Nothing.
"""
self._schema = value
# If schema is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['schema']
except KeyError:
pass
else:
self._connectionXML.set('schema', value)
@property
def http_path(self):
"""http_path."""
return self._http_path
@http_path.setter
def http_path(self, value):
"""Set the connection's http_path property.
Args:
value: New http_path value. String.
Returns:
Nothing.
"""
self._http_path = value
# If http_path is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['http-path']
except KeyError:
pass
else:
self._connectionXML.set('http-path', value)
@property
def connection_type(self):
"""Initial SQL to be run."""
return self._connection_type
@connection_type.setter
def connection_type(self, value):
"""Set the connection's connection_type property.
Args:
value: New connection_type value. Integer.
Returns:
Nothing.
"""
self._connection_type = value
# If connection_type is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['connection-type']
except KeyError:
pass
else:
self._connectionXML.set('connection-type', value)
@property
def sslcert(self):
"""sslcert."""
return self._sslcert
@sslcert.setter
def sslcert(self, value):
"""Set the connection's sslcert property.
Args:
value: New sslcert value. String.
Returns:
Nothing.
"""
self._sslcert = value
# If sslcert is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['sslcert']
except KeyError:
pass
else:
self._connectionXML.set('sslcert', value)
@property
def sslmode(self):
"""sslmode."""
return self._sslmode
@sslmode.setter
def sslmode(self, value):
"""Set the connection's sslcert property.
Args:
value: New sslcert value. String.
Returns:
Nothing.
"""
self._sslmode = value
# If sslmode is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['sslmode']
except KeyError:
pass
else:
self._connectionXML.set('sslmode', value)`
Hi,
I’m interested in using the Document API to update the connection type for .twbx files. I would like to update the following fields for a Hortonworks Hadoop Hive connection type: • Server Name • Authentication • Realm • Host FQDN • Service Name
If this is not possible with the current version, I would like to submit this as a feature request. These are only the fields that I need, but all field options on the Hortonworks connector would be helpful as well.
It would be great if I could do this not only locally, but also with a workbook that is published on Tableau Server. The Tableau Server UI doesn’t allow me to edit the authentication type for a data source and I haven’t seen a way to do this with tabcmd.
Also, I tried to access the Examples link at the bottom of the Github page (https://github.com/tableau/document-api-python) and it seems like the link is dead.
Thanks for your help!
Alex