Chef Server 12.2.0-1.
I'm trying to find a way to query Ohai node attributes from the PostgreSQL database. Having browsed through the table schemas and data, I'm not seeing any tables that would contain those attributes.
Are these attributes stored on Chef server? Is there a way to view them remotely via a database query or a REST call?
List of opscode_chef tables:
checksums
clients
containers
cookbook_artifact_version_checksums
cookbook_artifact_versions
cookbook_artifacts
cookbook_version_checksums
cookbook_versions
cookbooks
data_bag_items
data_bags
environments
groups
keys
node_policy
nodes
opc_customers
opc_users
org_migration_state
org_user_associations
org_user_invites
orgs
policies
policy_groups
policy_revisions
policy_revisions_policy_groups_association
roles
sandboxed_checksums
users
UPDATE 1: Thanks to #Tensibai.
Attributes are stored in table nodes, column serialized_object. The column serialized_object is gzip encoded.
Java code to fetch attributes in json:
String query = "SELECT name, serialized_object FROM nodes";
PreparedStatement st = conn.prepareStatement(query);
ResultSet rs = st.executeQuery();
while (rs.next()) {
String name = rs.getString("name");
byte[] arr = rs.getBytes("serialized_object");
byte[] out = unzip(arr);
System.out.println(name + " : " + new String(out));
}
public static byte[] unzip(byte[] in) throws IOException{
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileUtils.copy(new GZIPInputStream(new ByteArrayInputStream(in)), out);
return out.toByteArray();
}
Sample attributes: https://gist.github.com/rodionos/cb744155539699b5c348
I'm not an expert in PostgreSQL. A better solution would probably be to enable a native decompression function as described here: https://github.com/chef/chef-server/issues/8#issuecomment-99152808
Related
I have about 10 tables that I load into a DataSet using a single DataAdapter in a sequence. During the load, I use only one DataAdapter, and I replace the table names and SELECT statements as required. I replace the table name and the SQL select statement and successively fill tables in the DataSet. Everything is done inside of two nested "using" statements to dispose of the connection and DataAdapter objects as shown below.
using (OleDbConnection conn = new OleDbConnection (Db.DbConnGet ())) {
using (var da = new OleDbDataAdapter (sql, conn)) {
tablename = "Table1";
da.SelectCommand.CommandText = $"Select * from {tablename}";
try {
da.Fill (hsdset, tablename);
} catch (Exception ex) {
...
}
tablename = "Table2";
da.SelectCommand.CommandText = $"Select * from {tablename}";
try {
da.Fill (hsdset, tablename);
} catch (Exception ex) {
...
}
}}
As you can see, the DataAdapter is disposed of once the loading is done, and I pass the DataSet around my application as necessary for reading data.
But now I have a need to update or extend the data in the dataset and get it back into the database. Updating the DataTables inside the dataset is not a problem - there are many examples on the net. I regenerated a new Connection and DataAdapter to do the update with a table in the existing, modified, strongly-typed DataSet, as follows.
using (OleDbConnection conn = new OleDbConnection (Db.DbConnGet ())) {
using (var da = new OleDbDataAdapter ("", conn)) {
// this is required; I don't know if it is used by Update
da.SelectCommand.CommandText = $"Select * from " + tablename;
try {
// build special update commands from the table->db differences
var cbuilder = new OleDbCommandBuilder (da);
da.Update (dset, "Layers");
} catch (Exception ex) {
...
}
}
}
}
My first question is, "Does the Update operation actually use the original SELECT statement to retrieve info from the database? If not, why is it required? I thought the DataSet kept track of modified rows, new rows, deleted rows, and so on. I thought updating could be done without reading the whole data table again? Or maybe it reads only the records that are marked as modified in the DataTable?
My second question is what is the best (or normal) way of working with DataSets and DataAdapters this way? Is it best practice to always save the original DataAdapters for later use, or is it good practice to create new ones like I did above? (Does the original DataAdapter keep any state information during the load that the newly-created DataAdapter would not have?) Thank you.
I have been able to link PostgreSQL to java. I have been able to display all the records in the table, however I unable to perform delete operation.
Here is my code:
con = DriverManager.getConnection(url, user, password);
String stm = "DELETE FROM hostdetails WHERE MAC = 'kzhdf'";
pst = con.prepareStatement(stm);
pst.executeUpdate();
Please note that MAC is a string field and is written in capital letters. This field does exist in the table.
The error that I am getting:
SEVERE: ERROR: column "mac" does not exist
When it comes to Postgresql and entity names (Tables, Columns, etc.) with UPPER CASE letters, you need to "escape" the word by placing it in "". Please refer to the documentation on this particular subject. So, your example would be written like this:
String stm = "DELETE FROM hostdetails WHERE \"MAC\" = 'kzhdf'";
On a side note, considering you are using prepared statements, you should not be setting the value directly in your SQL statement.
con = DriverManager.getConnection(url, user, password);
String stm = "DELETE FROM hostdetails WHERE \"MAC\" = ?";
pst = con.prepareStatement(stm);
pst.setString(1, "kzhdf");
pst.executeUpdate();
I'm trying to create a project with EF6.1 with code-first. All works fine I have migration is enabled, create and update DB works too. Now my Problem:
I have create a table "VersionHistory" and a CompanyInfo table.
I'm writing an "Upgrade Wizzard" for update the database. Is it possible to get data from this tables to Display Information (e.g. YourCompanyName and Update from Program Version 1.x to 1.y) before I start the database update?
Should I use classic SQLConnection for this?
Many thanks
You can use a SQL Connection (it can be the same of EF) or you can disable EF database structure checking.
System.Data.Entity.Database.SetInitializer<MyModel>(null);
EDIT
If you access to an entity that is not updated on the database, you can receive Ado exceptions from EF (i.e. missing columns, missing tables and so on).
In compliance with "bubi" I will use a SQLConnection based on my Context e.g.
using (var ctx = new AppContext()) {
ctx.Database.Connection.Open();
var cmd = ctx.Database.Connection.CreateCommand();
cmd.CommandText = "Select * From CompanyInfo";
var rdr = cmd.ExecuteReader();
var infos = (from row in rdr.Cast<System.Data.Common.DbDataRecord>()
let entityId = (int)row["EntityId"] //internal key
let entityKey = (string)row["EntityKey"] //visible key
let displayname = (string)row["DisplayName"] //company name
// some more stuff (version, etc.)
select new NOCompanyInfo {
EntityId = entityId,
EntityKey = entityKey,
DisplayName = displayname,
DBName = dbName,
...
}).ToList();
return new ObservableCollection<NOCompanyInfo>(infos);
}
Thanks
These are the basic things I know about iDB2Commands to be used in Visual Studio 2010. Could you please help me how could I extract data from DB2? I know INSERT, DELETE and Record Count. But SELECT or Extract Data and UPDATE I don't know.
Imports IBM.Data.DB2
Imports IBM.Data.DB2.iSeries
Public conn As New iDB2Connection
Public str As String = "Datasource=10.0.1.11;UserID=edith;password=edith;DefaultCollection=impexplib"
Dim cmdUpdate As New iDB2Command
Dim sqlUpdate As String
conn = New iDB2Connection(str)
conn.Open()
'*****Delete Records and working fine
sqlUpdate = "DELETE FROM expusers WHERE username<>#username"
cmdUpdate.Parameters.Add("username", iDB2DbType.iDB2Date)
cmdUpdate.Parameters("username").Value = ""
'*****Insert Records and working fine
sqlUpdate = "INSERT INTO expusers (username, password, fullname) VALUES (#username, #password, #fullname)"
cmdUpdate.Parameters.Add("username", iDB2DbType.iDB2VarChar)
cmdUpdate.Parameters.Add("password", iDB2DbType.iDB2VarChar)
cmdUpdate.Parameters.Add("fullname", iDB2DbType.iDB2VarChar)
cmdUpdate.Parameters("username").Value = txtUsername.Text
cmdUpdate.Parameters("password").Value = txtPassword.Text
cmdUpdate.Parameters("fullname").Value = "Editha D. Gacusana"
'*****Count Total Records and working fine
Dim sqlCount As String
Dim cmd As New iDB2Command
sqlCount = "SELECT COUNT(*) AS count FROM import"
cmd = New iDB2Command(Sql, conn)
Dim count As Integer
count = Convert.ToInt32(cmd.ExecuteScalar)
'*****Update Records and IT IS NOT WORKING AT ALL
sqlUpdate = "UPDATE expusers SET password = #password WHERE RECNO = #recno"
cmdUpdate.Parameters.Add("recno", iDB2DbType.iDB2Integer)
cmdUpdate.Parameters.Add("password", iDB2DbType.iDB2VarChar)
cmdUpdate.Parameters("recno").Value = 61
cmdUpdate.Parameters("password").Value = txtPassword.Text
cmdUpdate.Connection = conn
cmdUpdate.CommandText = sqlUpdate
cmdUpdate.ExecuteNonQuery()
conn.Close()
Please help me how to code the SELECT query wherein I could extract/fetch data from DB2 Database. Also, how could i update the records in the database.
Thanks!
Instead of ExecuteNonQuery(), look at ExecuteReader(). I don't have VS2010 installed, but try something like this:
iDB2Command cmdSelect = new iDB2Command("SELECT username, password, fullname FROM expusers", conn);
cmdSelect.CommandTimeout = 0;
iDB2DataAdapter da = new iDB2DataAdapter(cmdSelect);
DataSet ds = new DataSet();
da.Fill(ds, "item_master");
GridView1.DataSource = ds.Tables["expusers"];
GridView1.DataBind();
Session["TaskTable"] = ds.Tables["expusers"];
da.Dispose();
cmdSelect.Dispose();
cn.Close();
See: http://gugiaji.wordpress.com/2011/12/29/connect-asp-net-to-db2-udb-for-iseries/
If you aren't trying to bind to a grid, look at iDB2Command.ExecuteReader() and iDB2DataReader()
The DELETE is working fine? The code has the parameter type for "username" set to iDB2Date. The INSERT has "username" set to iDB2VarChar. How is the column defined in the table? Char, Varchar or Date?
On the UPDATE, you reference RECNO, but that does not seem to be a column in the table. Updating a relational database table by row number is a bad idea - the row numbers are not guaranteed to stay constant. If you are just testing, as I think you are, don't use RECNO, use RRN(). The DB2 for i syntax is WHERE rrn(expusers) = #recno
To help your testing, do a SELECT without a WHERE clause and list out all the rows. Make sure the name stored in the username column matches the name you are trying to update. Pay particular attention to the case of the data. If the name in expusers looks like "EDITHA D. GACUSANA", and #username is "Editha D. Gacusana" then it will not match on the WHERE clause.
We are trying to build an EntityConnection dynamically so that different users are connecting to differnet databases determined at run-time. In order to do this we are testing the code found here: http://msdn.microsoft.com/en-us/library/bb738533.aspx. We have implemented this below:
' Specify the provider name, server and database.
Dim providerName As String = "System.Data.SqlClient"
Dim serverName As String = "OurDBServerName"
Dim databaseName As String = "OurDBName"
' Initialize the connection string builder for the
' underlying provider.
Dim sqlBuilder As New SqlConnectionStringBuilder
' Set the properties for the data source.
sqlBuilder.DataSource = serverName
sqlBuilder.InitialCatalog = databaseName
sqlBuilder.IntegratedSecurity = False
sqlBuilder.UserID = "OurAppUserName"
sqlBuilder.Password = "OurPassword"
' Build the SqlConnection connection string.
Dim providerString As String = sqlBuilder.ToString
' Initialize the EntityConnectionStringBuilder.
Dim entityBuilder As New EntityConnectionStringBuilder
'Set the provider name.
entityBuilder.Provider = providerName
' Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString
' Set the Metadata location to the current directory.
entityBuilder.Metadata = "res://*/NotaModel.csdl|" & _
"res://*/NotaModel.ssdl|" & _
"res://*/NotaModel.msl"
Console.WriteLine(entityBuilder.ToString)
Using conn As EntityConnection = New EntityConnection(entityBuilder.ToString)
conn.Open()
Console.WriteLine("Just testing the connection.")
conn.Close()
End Using
When the conn.Open() is run an error is thrown: "Unable to load the specified metadata resource." It seems to indicate that one or more of the "res://*..." references is wrong. I have confirmed that the project does indeed contain these files (under the bin/debug folder). What are we missing here - any ideas?
Thanks
Yes, the res:// part is wrong. Look at the resource names in Reflector (inside the assembly), not on your local filesystem, to see what they should be.