Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for YAML and Helm chart static analysis #582

Open
wants to merge 74 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
f21d3a0
Model layer of Yaml Parser
rizwankadhar Mar 26, 2022
aa0bd25
Added Model layer of Yaml Parser
rizwankadhar Mar 26, 2022
2faecd6
Added the parser layer of the YamlParser plugin
rizwankadhar Apr 17, 2022
d99ee72
Added the parser layer of the YamlParser plugin
rizwankadhar Apr 17, 2022
78433b2
Model layer of Yaml Parser
rizwankadhar Mar 26, 2022
168e5f5
Added the parser layer of the YamlParser plugin
rizwankadhar Apr 17, 2022
7db9f02
YamlParser persists whole Yaml file
rizwankadhar Apr 18, 2022
5fde274
Merge branch 'yaml' of https://github.com/rizwankadhar/CodeCompass in…
rizwankadhar Apr 18, 2022
4d00b66
Removed unnecessary columns
rizwankadhar Apr 18, 2022
2694d79
Added Yaml file usage identification
rizwankadhar Apr 23, 2022
617490a
Added service layer and web plugin
rizwankadhar May 3, 2022
03948e1
Added ryml code
rizwankadhar May 3, 2022
a1ea3bd
Fixed runtime issues with YAML service.
intjftw May 3, 2022
d1e0f57
Added a sample code to reach nested nodes.
intjftw May 5, 2022
542cd5c
Removed Unnecessary parameters and commented lines of code
rizwankadhar May 8, 2022
baa130d
Added parent column to the YamlContent table and populated it
rizwankadhar May 17, 2022
323d121
Fixed YamlService to return only the data of the clicked file, added …
rizwankadhar May 17, 2022
d2da47c
YamlInfo menuItem displays type, path, number of key-data pairs and i…
rizwankadhar May 21, 2022
ca9c294
YamlParser now traverses the sequences recursively
rizwankadhar May 21, 2022
621a333
Added a parent value for all the sequence elements
rizwankadhar May 21, 2022
05f9063
Pair with empty data field is also persisted. Removed unnecessary code
rizwankadhar May 22, 2022
1f1f728
Improved the view of the Yaml information displayed on Webserver-HTML
rizwankadhar May 22, 2022
19656ba
Organized code as per CodeCompass coding conventions
rizwankadhar May 24, 2022
013ff98
Starting to transform the YAML plugin to be a full language plugin.
intjftw Jun 15, 2022
a6c53db
Switched to yaml-cpp instead of rapidyaml. YamlAstNodes are built.
intjftw Jun 16, 2022
7c376fb
Recursive parsing of YAML files according to node types, exception ha…
intjftw Jun 17, 2022
3839a6f
Recursive parsing of YAML files enhanced, syntax highlight added (in …
intjftw Jun 21, 2022
2b35b0e
Node clicking error is corrected.
intjftw Jun 27, 2022
7518b36
Various modifications.
intjftw Jul 11, 2022
0e36da6
Info tree is ready for YAML nodes.
intjftw Jul 11, 2022
83ff400
Diagrams re-added, root keys are parsed with full values.
intjftw Jul 12, 2022
b35196d
Major refactor in service.
intjftw Jul 13, 2022
2a4e220
Multithreading works in parser.
intjftw Jul 18, 2022
8a0b964
Multithreading works in parser.
intjftw Jul 18, 2022
f70f203
Parsing microservices and showing microservice diagram on web.
intjftw Jul 18, 2022
ee47f79
Adding edges to store connections between microservices.
intjftw Jul 19, 2022
6449c4c
Added relation collector class.
intjftw Jul 25, 2022
89f4a50
Relation collector developed.
intjftw Aug 8, 2022
9c6fdf0
Relation collector error fixed, relations between automatically detec…
intjftw Aug 12, 2022
76319ff
Adding yaml-cpp to CI.
intjftw Aug 12, 2022
daee3fa
Adding microservice relations diagram to web service.
intjftw Aug 21, 2022
fec8e1a
Microservice relations diagram showing dynamic relation type.
intjftw Aug 30, 2022
8f4b246
Minor changes for PR.
intjftw Sep 16, 2022
42217ef
Edit processing according to specific Kubernetes rules.
intjftw Sep 28, 2022
f10b560
Merge branch 'master' into yaml
intjftw Sep 28, 2022
2ff2861
Early trials.
intjftw Sep 29, 2022
360adf1
Starting helm template parsing.
intjftw Sep 29, 2022
f6ec770
Started to implement helm template parsing.
intjftw Oct 12, 2022
ddf0220
Finished parsing Service templates.
intjftw Oct 13, 2022
d541690
Processing aliased microservices in integration chart.
intjftw Oct 13, 2022
78434f2
Transformed Yaml service to extend Language service, and added a new …
intjftw Oct 14, 2022
64d8137
Added event handler to the microservice navigator menu.
intjftw Oct 19, 2022
7764bac
Modified model, parsing and diagram generation.
intjftw Oct 20, 2022
2aae5cb
Finding arbitrary key in a yaml file.
intjftw Nov 6, 2022
da2d535
Implemented the rules of mount dependency type.
intjftw Nov 13, 2022
20c75ad
Implemented the rules of certificate dependency type, and added diffe…
intjftw Nov 15, 2022
006061d
Corrected an error of helm template ids in parsing.
intjftw Nov 16, 2022
ceb82b0
Fixed microservice detection in subcharts and removed debug messages.
intjftw Nov 16, 2022
e3282e4
Fixed multiplied arrows in k8s diagrams.
intjftw Nov 29, 2022
9ce0c99
Parsing resources.
intjftw Nov 30, 2022
d215660
Resource usage diagram added.
intjftw Nov 30, 2022
2c8697c
Guarantee that microservices will be processed independent of the fil…
intjftw Dec 1, 2022
9015118
Processing values.yaml files to get more service relations.
intjftw Dec 7, 2022
1250090
Complementing Service manifest diagram with back and forth dependencies.
intjftw Dec 7, 2022
f9e1c09
Fixing the detection of microservices to not depend on the order of f…
intjftw Dec 18, 2022
64db368
Documentation and other things.
intjftw Feb 4, 2023
385a361
Improving documentation.
intjftw Feb 14, 2023
b51de7d
Renamed the plugin to helm as it is more precise. Also renamed the va…
intjftw Feb 15, 2023
9155e7c
Complemented documentation and user guide.
intjftw Feb 16, 2023
71047a8
Merge branch 'master' into yaml
mcserep Aug 10, 2023
700bbf1
PR change requests: unified naming and more small modifications.
intjftw Aug 21, 2023
bbf4e81
PR change requests.
intjftw Aug 22, 2023
5d98aee
Merge branch 'master' into yaml
mcserep Sep 9, 2023
ef7bea8
Add missing inclusion dependency in HelmService for LanguageService f…
mcserep Sep 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added Yaml file usage identification
Now yaml files can be classified as kubernetes
config, CI, Helm Chart or Other file.
  • Loading branch information
rizwankadhar committed Apr 23, 2022
commit 2694d79c85822c2aa59602946e8153d6a7797a1c
2 changes: 1 addition & 1 deletion plugins/yaml/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
add_subdirectory(model)
add_subdirectory(parser)
add_subdirectory(parser)
4 changes: 3 additions & 1 deletion plugins/yaml/model/include/model/yaml.h
Original file line number Diff line number Diff line change
@@ -19,11 +19,13 @@ struct Yaml
{
enum Type
{
KUBERNETES_CONFIG,
DOCKERFILE,
HELM_CHART,
CI,
OTHER
};


#pragma db id auto
std::uint64_t id;

4 changes: 3 additions & 1 deletion plugins/yaml/model/include/model/yamlcontent.h
Original file line number Diff line number Diff line change
@@ -23,9 +23,11 @@ struct YamlContent
#pragma db not_null
std::string data;

#pragma db not_null
FileId file;

#pragma db id auto
std::uint64_t id;

};


33 changes: 26 additions & 7 deletions plugins/yaml/parser/include/yamlparser/yamlparser.h
Original file line number Diff line number Diff line change
@@ -23,26 +23,45 @@ class YamlParser : public AbstractParser

private:
util::DirIterCallback getParserCallback();

enum Type
{
KUBERNETES_CONFIG,
DOCKERFILE,
HELM_CHART,
CI,
OTHER
};
struct keyData {
ryml::csubstr key;
ryml::csubstr parent;
// ryml::csubstr parent;
ryml::csubstr data;
keyData() {}
keyData(ryml::csubstr k, ryml::csubstr p, ryml::csubstr d) : key(k), parent(p), data(d) {}
keyData(ryml::csubstr k, ryml::csubstr d) : key(k), data(d) {}

friend std::ostream& operator<<(std::ostream &os, const keyData &kd)
{
os << kd.key << " " << kd.parent << " " << kd.data << std::endl;
os << kd.key << " " << kd.data << std::endl;
return os;
}
};

std::vector<keyData> getDataFromFile(model::FilePtr file_) const;
std::vector<keyData> getDataFromFile(model::FilePtr file_, Type &type) const;
bool accept(const std::string& path_) const;
bool isCI (std::string const &filename, std::string const &ending)
{
if (filename.length() >= ending.length())
{
return (0 == filename.compare (filename.length() - ending.length(), ending.length(), ending));
}
else
{
return false;
}
}
// std::vector<keyData> duplicate(std::vector<keyData> kdata);

void persistData(const std::vector<keyData>& data_, model::FileId file_);

// void persistData(const std::vector<keyData>& data_, model::FileId file_, Type type);
void persistData(model::FilePtr file_, model::FileId fileId_);
std::unordered_set<model::FileId> _fileIdCache;
std::unique_ptr<util::JobQueueThreadPool<std::string>> _pool;
std::atomic<int> _visitedFileCount;
197 changes: 103 additions & 94 deletions plugins/yaml/parser/src/yamlparser.cpp
Original file line number Diff line number Diff line change
@@ -72,6 +72,15 @@ void file_put_contents(const char *filename, const char *buf, size_t sz, const c
}


// std::vector<YamlParser::keyData> YamlParser::duplicate(std::vector<YamlParser::keyData> kdata)
// {
// for (keyData kd : kdata)
// {
// LOG(info) <<"In DUPLICATE: " << kd.key << " " << " " << kd.data << std::endl;
// }
// return kdata;
// }


YamlParser::YamlParser(ParserContext& ctx_): AbstractParser(ctx_)
{
@@ -97,7 +106,7 @@ YamlParser::YamlParser(ParserContext& ctx_): AbstractParser(ctx_)
}
});

int threadNum = _ctx.options["jobs"].as<int>();///Not needed probably
int threadNum = 1;//_ctx.options["jobs"].as<int>();///Not needed probably
_pool = util::make_thread_pool<std::string>(
threadNum, [this](const std::string& path_)
{
@@ -106,10 +115,27 @@ YamlParser::YamlParser(ParserContext& ctx_): AbstractParser(ctx_)
{
if (_fileIdCache.find(file->id) == _fileIdCache.end())
{
std::vector<keyData> kd = getDataFromFile(file);
// LOG(info) << "DEBUG: In Ctr path is: " << path_ << std::endl;
this->persistData(kd, file->id);
++this->_visitedFileCount;
if (accept(file->path))
{
// Type type;
// std::vector<keyData> ked = getDataFromFile(file, type);

// LOG(info) << "In Ctr, size is: " << ked.size() << std::endl;

// for (keyData kd : ked)
// {
// LOG(info) <<"In CTR: " << kd.key << " " << " " << kd.data << std::endl;
// }
// std::vector<keyData> final = duplicate(ked);
// for (keyData kd : final)
// {
// LOG(info) <<"In CTR FINAL: " << kd.key << " " << " " << kd.data << std::endl;
// }
// LOG(info) << "DEBUG: In Ctr path is: " << path_ << std::endl;
this->persistData(file, file->id);
++this->_visitedFileCount;
}

}
else
LOG(debug) << "YamlParser already parsed this file: " << file->path;
@@ -252,70 +278,57 @@ util::DirIterCallback YamlParser::getParserCallback()
bool YamlParser::accept(const std::string& path_) const
{
std::string ext = boost::filesystem::extension(path_);
return ext == ".yaml";
std::string cmd = "file " + path_ + " >test.txt";
int status = std::system(cmd.c_str()); // execute the UNIX command "ls -l >test.txt"
std::string tmp, ascii, text;
std::ifstream("test.txt") >> tmp >> ascii >> text;
std::system("rm -rf test.txt");
std::string fileType = ascii + " " + text;
return ext == ".yaml" && fileType == "ASCII text";// && result == "ASCII text";
}
/**
* Here I think we can use our yamlparsering libraries and grab the useful content
* from the files and then tranform them to put them into db
*/
std::vector<YamlParser::keyData> YamlParser::getDataFromFile(model::FilePtr file_) const
std::vector<YamlParser::keyData> YamlParser::getDataFromFile(model::FilePtr file_, Type &type) const
{
// Loc result;

// LOG(debug) << "Count metrics for " << file_->path;

// //--- Get source code ---//

// std::string content
// = file_->content ? file_->content.load()->content : std::string();

// if (content.empty())
// return result;

// //--- Original lines ---//

// result.originalLines = std::count(content.begin(), content.end(), '\n') + 1;

// //--- Non blank lines ---//

// eraseBlankLines(content);

// result.nonblankLines = std::count(content.begin(), content.end(), '\n') + 1;

// //--- Code lines ---//

// std::string singleComment, multiCommentStart, multiCommentEnd;

// setCommentTypes(
// file_->type, singleComment, multiCommentStart, multiCommentEnd);
// eraseComments(
// content, singleComment, multiCommentStart, multiCommentEnd);

// result.codeLines = std::count(content.begin(), content.end(), '\n') + 1;

// return result;
std::vector<keyData> keysDataPairs;
if (accept(file_->path))
{
std::string contents = file_get_contents<std::string>(file_->path.c_str());///file_->content ? file_->content.load()->content : std::string("nothing here");
// LOG(info) << "DEBUG: In getDataFromFile, contents are: " << contents << std::endl;
ryml::Tree yamlTree = ryml::parse_in_arena(ryml::to_csubstr(contents));
std::stringstream ss;
ss << yamlTree;
if (yamlTree["apiVersion"].has_key())
{
if (yamlTree["name"].has_key() && yamlTree["version"].has_key())
{
type = Type::HELM_CHART;
}
else if (yamlTree["kind"].has_key())
{
type = Type::KUBERNETES_CONFIG;
}
}
else
{
type = Type::OTHER;
}
// std::stringstream ss;
// ss << yamlTree;
// LOG(info) << "DEBUG: In getDataFromFile, tree is: " << ss.str() << std::endl;
ryml::NodeRef root = yamlTree.rootref();


for (ryml::NodeRef n : root.children())
{
// LOG(info) << "DEBUG: In getDataFromFile, loopworks: " <<std::endl;
keysDataPairs.push_back(keyData(n.has_key() ? n.key() : ryml::csubstr{}, ryml::csubstr{}, n.has_val() ? n.val() : ryml::csubstr{}));
keysDataPairs.push_back(keyData(n.has_key() ? n.key() : ryml::csubstr{}, n.has_val() ? n.val() : ryml::csubstr{}));
}

// LOG(info) << "DEBUG: In getDataFromFile, size is: " << keysDataPairs.size() << std::endl;
LOG(info) << "DEBUG: In getDataFromFile, size is: " << keysDataPairs.size() << std::endl;
for (keyData kd : keysDataPairs)
{
std::cout <<"DEBUG: In getDataFromFile " << kd;
LOG(info) <<" In getDataFromFile " << kd;
}
}
return keysDataPairs;
@@ -327,29 +340,47 @@ std::vector<YamlParser::keyData> YamlParser::getDataFromFile(model::FilePtr file
* Getting Loc(useful data) and putting it into the db, it is actually populating the
* db object we created in model/yaml.h. It is using transaction
*/
void YamlParser::persistData(const std::vector<keyData>& data_, model::FileId file_)
// void YamlParser::persistData(const std::vector<keyData>& data_, model::FileId file_, Type type)
void YamlParser::persistData(model::FilePtr file_, model::FileId fileId_)
{
// util::OdbTransaction trans(_ctx.db);
// trans([&, this]{
// model::Yaml yaml;
// yaml.file = file_;

// yaml.type = model::Yaml::OTHER;
// LOG(info) << "Yaml is: " << yaml.file << " " << yaml.type << std::endl;
// _ctx.db->persist(yaml);
// });
int i = 0;
for (keyData kd : data_)
Type type;
std::vector<keyData> keysDataPairs;
std::string contents = file_get_contents<std::string>(file_->path.c_str());///file_->content ? file_->content.load()->content : std::string("nothing here");
ryml::Tree yamlTree = ryml::parse_in_arena(ryml::to_csubstr(contents));
if (yamlTree["apiVersion"].has_key())
{
i++;
if (i==1) continue;
util::OdbTransaction trans(_ctx.db);
trans([&, this]{
// LOG(info) << "YamlContent is: " << data_.size() << std::endl;

// std::cout <<"DEBUG: In persistdata " << kd;
if (yamlTree["name"].has_key() && yamlTree["version"].has_key())
{
type = Type::HELM_CHART;
}
else if (yamlTree["kind"].has_key())
{
type = Type::KUBERNETES_CONFIG;
}
}
else if (isCI(file_->path, "ci.yaml") || isCI(file_->path, "ci.yml") )
{
type = Type::CI;
}
else
{
type = Type::OTHER;
}
ryml::NodeRef root = yamlTree.rootref();


for (ryml::NodeRef n : root.children())
{
keysDataPairs.push_back(keyData(n.has_key() ? n.key() : ryml::csubstr{}, n.has_val() ? n.val() : ryml::csubstr{}));
}
util::OdbTransaction trans(_ctx.db);
trans([&, this]{
for (keyData kd : keysDataPairs)
{
LOG(info) << "In PersistData: YamlKeydata is: " << kd;

model::YamlContent yamlContent;
// yamlContent.file = file_;
yamlContent.file = fileId_;
std::stringstream ss;
ss << kd.key;
yamlContent.key = ss.str();///ryml::emitrs<std::string>(kd.key);
@@ -358,34 +389,12 @@ void YamlParser::persistData(const std::vector<keyData>& data_, model::FileId fi
yamlContent.data = ss.str(); ///ryml::emitrs<std::string>(kd.data);//ryml::to_csubstr(kd.data);
LOG(info) << "YamlContent is: " << yamlContent.key << " " << yamlContent.data << std::endl;
_ctx.db->persist(yamlContent);
});
}
// util::OdbTransaction trans(_ctx.db);
// trans([&, this]{
// model::Metrics metrics;
// metrics.file = file_;

// if (loc_.codeLines != 0)
// {
// metrics.type = model::Metrics::CODE_LOC;
// metrics.metric = loc_.codeLines;
// _ctx.db->persist(metrics);
// }

// if (loc_.nonblankLines != 0)
// {
// metrics.type = model::Metrics::NONBLANK_LOC;
// metrics.metric = loc_.nonblankLines;
// _ctx.db->persist(metrics);
// }

// if (loc_.originalLines != 0)
// {
// metrics.type = model::Metrics::ORIGINAL_LOC;
// metrics.metric = loc_.originalLines;
// _ctx.db->persist(metrics);
// }
//});
}
model::Yaml yaml;
yaml.file = fileId_;
yaml.type = model::Yaml::Type(type);
_ctx.db->persist(yaml);
});
}

#pragma clang diagnostic push